AtCoder Beginners Selection in Bash 完走
https://t.co/qFatTDC1Rl においてC++より人気っぽい言語を選んできたので次はここから言語を選んでABSを解きます
— Naomi Yuritani (@NaomiatLibrary) 2019年6月27日
AtCoder Beginners Selection
atcoder.jp
Haskell
naomi-notebook.hatenablog.com
Javascript
naomi-notebook.hatenablog.com
BashでACしていきます。
Bashは触ったこともないし、どういう時に適している言語なのかすらよくわかっていません。以下のサイトを見て、あとは適宜ググりまくってやっていきます…
http://furyo.on-air.ne.jp/linux/bash.html
ABC088B - Card Game for Two以前は(慣れていなかったので)フィルターの形を使わず、ABC088B - Card Game for Two以降はフィルターの形で解いています
PracticeA - Welcome to AtCoder
read a read b c read s echo $((a+b+c)) $s
ABC081A - Placing Marbles
0で始まる数字は8進法だと思われてしまうので以下だとWA
read a echo $((a%10+(a/10)%10+(a/100)%10))
10進数に直せる。
read a a=10#$a echo $((a%10+(a/10)%10+(a/100)%10))
ABC081B - Shift only
標準入力から配列に格納するのをしばらく調べていたけど、実は-aオプションでやってくれるらしい。
ここら辺も見ておくと良さそうメモ
read コマンドの使い方 - 拡張 POSIX シェルスクリプト Advent Calendar 2013 - ダメ出し Blog
read n read -a a ans=0 while true;do for i in ${!a[@]};do if [ $((a[i]%2)) -eq 0 ];then a[$i]=$((a[i]/2)) else echo $ans exit fi done ans=$((ans+1)) done
ABC087B - Coins
これがTLEマジ?50^3=125000<=10^6しかループしてないんだけど…
read a read b read c read x ans=0 for i in `seq 0 $a`;do for j in `seq 0 $b`;do for k in `seq 0 $c`;do if [ $((500*i+100*j+50*k)) -eq $x ];then ans=$((ans+1)) fi done done done echo $ans
調べてみたら10^4~10^5くらいしか計算できないみたいです。ええ…
read a read b read c read x ans=0 for i in `seq 0 $a`;do for j in `seq 0 $b`;do k=$(( (x-500*i-100*j)/50 )); if [ $k -le $c -a $k -ge 0 ];then ans=$((ans+1)) fi done done echo $ans
ABC083B - Some Sums
これでTLEして(まさか10^4で死んでいる…?)ってなったんですが、関係ない$*1をans=$*2に警告が出ないように直したらACしました。なんでですか?
(追記)
教えていただきました!$*3で、その計算結果のようなコマンドを探して見つかりませんでした、という警告が出るのですが、どうやらそのコマンドを探すのに実は時間がかかっているらしいです。
Some SumsのTLEについてですが、$((ans+=i))だと例えば1とか2という名前のコマンドを呼び出そうとしていて、それが存在しないことに気づくのに時間がかかっていると思います
— こたつがめ (@kotatsugame_t) 2019年6月28日
競プロとかコードゴルフをやっていると警告を無視する人間になりがちですが、本来出ないようにするべきですよね…
WA
read N A B ans=0 for (( i=1; i<=$N; i++ ));do s=$((i%10+(i/10)%10+(i/100)%10+(i/1000)%10+(i/10000)%10)) if [ $s -le $B -a $s -ge $A ];then $((ans+=i)) fi done echo $ans
AC
read N A B ans=0 for (( i=1; i<=$N; i++ ));do s=$((i%10+(i/10)%10+(i/100)%10+(i/1000)%10+(i/10000)%10)) if [ $s -le $B -a $s -ge $A ];then ans=$((ans+i)) fi done echo $ans
ABC088B - Card Game for Two
ここでフィルタを利用した文字列操作に目覚めたので色々工夫し始める
Linuxのテキストフィルタコマンドであそんでみよう - Qiita
フィルタを使用した文字列操作 1 | UNIX & Linux コマンド・シェルスクリプト リファレンス
【 awk 】コマンド(基本編その3)――テキストの加工とパターン処理・BEGIN・ENDとAWKスクリプト:Linux基本コマンドTips(117) - @IT
このあたり参考にした
sed 1d | sed -e 's/ /\n/g' | sort -rn | paste - - | awk 'BEGIN{a=0;b=0}{a+=$1;b+=$2}END{print (a-b)}'
ABC085B - Kagami Mochi
sed 1d | sort -n | uniq | wc -l
ABC085C-Otoshidama
いやフィルター使ってるけどこれはほとんど前半そのままって感じだ
awk 'BEGIN{sum+=0;can=false}{n=$1;y=$2;for(a=0;a<=n;a++)for(b=0;a+b<=n;b++)if(a*10000+b*5000+(n-a-b)*1000==y){print a,b,n-a-b;exit}print "-1 -1 -1"}END{}'
ABC049C - 白昼夢 / Daydream
javascriptと同じく正規表現。
注意としては|のor演算子を使うが、そのためには拡張正規表現を使う必要があるため、-Eオプションをつけなければならない。
grep -cE '^(dream|dreamer|erase|eraser)+$' | sed s/1/YES/g | sed s/0/NO/g