Naomi's notebook

Naomi's notebook

AtCoder Beginners Selection in Ruby 完走

順番的には次はPHPだけどC++Javaに影響を受けたっぽいしそんなに代わり映えしないだろうか?


…というわけで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)でした!やったあ!
f:id:Naomi_Lilienthal:20190629103509p:plain

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"