AtCoder Beginners Selection in Ruby 完走
順番的には次はPHPだけどC++とJavaに影響を受けたっぽいしそんなに代わり映えしないだろうか?
…
Ruby!!!!(純粋関数型言語との壁は大きいのでHaskellほどではありませんが……)
— 竹麻呂 (@Takemaro_001) 2019年6月28日
…というわけでRubyをやります:-)
ちなみにRubyは五月祭2019 Live Codegolf Contest day2で見たことがある程度です。書いたことはなかったです。
途中から短くするのが結構楽しくなりました。
Haskell
AtCoder Beginners Selection in Haskell 完走 - Naomi's notebook
JavaScript
AtCoder Beginners Selection in JavaScript 完走 - Naomi's notebook
Bash
AtCoder Beginners Selection in Bash 完走 - Naomi's notebook
Java
AtCoder Beginners Selection in Java - Naomi's notebook
Welcome to AtCoder
せっかくなので軽く調べると、普通に使うブロックの形のmap{|x| xの処理}(またはdo...end)の代わりに、そのブロックをProcというクラスのオブジェクトにすることで扱いやすくなることができるのでそれを渡していて、&はそれをブロックとして展開しているようです。:to_sはメソッド.to_sのシンボルを渡している。
rubyのコードを見てyieldってなんだろうと思っていたのですが、これもブロックを展開する系でdef func のなかでyieldを使うとそこで受け取ったblockの処理を行うことができるようだ、便利そう。
a=gets.to_i() b,c=gets.chomp.split(" ").map(&:to_i); s=gets.chomp print (a+b+c).to_s+" "+s
print "#{a+b+c} #{s}\n"という書き方で#{}内の式を展開できるのか(サンプルより)。
ABC086A - Product
print gets.chomp.split(" ").map(&:to_i).all?{|x|x%2>0}?"Odd":"Even";
ワンライン。何個値があってもAC
ABC081A Placing Marbles
print gets.count("1")
ABC081B Shift only
rubyはインクリメントできない…!
あと最初にハマったのはdiv2roop= Proc.new{ ...でProcとして作ると、return ansで全部抜けてしまってprintすらされないのでlambdaにする。lambdaは引数の数が違っているとエラーを返すだけでProcオブジェクトの一つなので、他はそのままで問題ないらしい(.to_procで帰ってくるのもlambda)。
div2roop = lambda {|x| ans=0 until x%2>0 do x>>=1 ans+=1 end return ans } p readlines[1].chomp.split(" ").map(&:to_i).map(&div2roop).min()
ABC087B Coins
solve = Proc.new{|n| ans=0 (n[0]+1).times{|i| (n[1]+1).times{|j| (n[2]+1).times{|k| ans+=i*500+j*100+k*50==n[3]?1:0; } } } print ans } solve.call(readlines.map(&:chomp).map(&:to_i))
ABC083B Some Sums
だいぶ工夫した。
これはWA。ArrayにSumというメゾットがないんだ…(paiza.ioでは動くのでバージョンが違うのかな?)
N,A,B=gets.chomp.split(" ").map(&:to_i) print [*(1..N)].map{|x| d=x.to_s.each_codepoint.to_a.map{|x|x-"0".ord}.sum() (A<=d&&d<=B)?x:0 }.sum()
inject(:+)で代用できる。injectとは(リファレンスより)
injectメソッドは、ブロックを使って繰り返し計算を行うのに使います。ブロックに順に「要素1、要素2」、「ブロックの前回の戻り値、要素3」、「ブロックの前回の戻り値、要素4」、...を渡します。
これ便利そう。AC:
N,A,B=gets.chomp.split(" ").map(&:to_i) print [*(1..N)].map{|x| d=x.to_s.each_codepoint.to_a.map{|y|y-"0".ord}.inject(:+) (A<=d&&d<=B)?x:0 }.inject(:+)
ABC088B Card Game for Two
これとってもよくないですか?
print readlines[1].split(" ").map(&:to_i).sort().inject{|x,y|-x+y}.abs
調べてみたらRubyのshortest code(68byte)でした!やったあ!
ABC085B Kagami Mochi
p readlines[1..-1].map(&:chomp).map(&:to_i).uniq().size()
これもshortest(59bytes)
ABC085C Otoshidama
めんどくさいのでshortest codeは目指しません
solve = Proc.new{|n| ans=0 (n[0]+1).times{|i| (n[0]+1-i).times{|j| if i*10000+j*5000+(n[0]-i-j)*1000==n[1] then print "#{i} #{j} #{n[0]-i-j}" exit 0 end } } print "-1 -1 -1" } solve.call(gets.split(" ").map(&:to_i))
shortest codeをみてみたらrepeated_combination(n)なるものを使っていた。
配列の要素から引数n個を選んだときの重複組合せ(順序なし、重複を許す組合せ)を数え上げます。
競プロでは結構便利そう
ABC049C 白昼夢 / Daydream
print gets.match(/^(erase|eraser|dream|dreamer)*$/)?"YES":"NO"
shortest codeをみたら正規表現の?(直前一文字省略可能)なるものが使われていてもっと短かった。なるほど
ABC086C Traveling
shortestではないけどそこそこ短い。明らかにabsあたりを工夫して短くできそう。
readlines[1..-1].map(&:split).map{|x|x.map(&:to_i)}.inject([0,0,0]){|t,n|;d=(t[0]-n[0]).abs-(t[1]-n[1]).abs-(t[2]-n[2]).abs;if d<0||d%2==1 then puts "No";exit 0 end;n} puts "Yes"