みなさん、こんにちは。まどぎわです(・∀・)
RubyKaigiでCookpadさんのブースで出題されていたRuby Puzzleを、Ruby Kaigi中に楽しくやっていたので、
解答も下記で公開されたので、自分の解答をメモしておきます。
techlife.cookpad.com
Day 1
Problem 1-1
puts "#{"Goodbye" .. "Hello"} world"
My Answer(2文字)
puts "#{"Goodbye" .. && "Hello"} world"
HintにあるようにRuby2.6から追加された終端なしRangeを使って、
"Hello"だけを返せればいいのかなと思ったので&&
を使ってみました。
www.ruby-lang.org
Problem 1-2
puts&.then {
"Hello world"
}
My Answer(2文字)
puts 1&.then {
"Hello world"
}
これはputs
の返り値が、nil
になってしまってthen
以降が実行されなくなっていたので、
puts 1&.then
として、puts
の返り値を使用しないようにしてました。
Problem 1-3
include Math
Out, *,
Count = $>,
$<, E ** (2 * PI)
Out.puts("Hello world" *
Count.abs.round)
My Answer (2文字)
include Math
Out, *,
Count = $>,
$<, E ** (2 * PI*0)
Out.puts("Hello world" *
Count.abs.round)
Countが1に近い値になれば、"Hello world"が1回実行されるので、
E ** (2 * PI*0)
として、1に近い値を作りました。
Day 2
Problem 2-1
def say
-> {
"Hello world"
}
yield
end
puts say { "Goodbye world" }
My Answer(1文字)
def say
-> {
"Hello world"
}.
yield
end
puts say { "Goodbye world" }
これは.yield
は.call
と同じなので、それを使うようにしました。
docs.ruby-lang.org
Problem 2-2
e = Enumerator.new do |g|
yield "Hello world"
end
puts e.next
My Answer(2文字)
e = Enumerator.new do |g|
g.yield "Hello world"
end
puts e.next
g
はEnumerator::Yielder
が返却される。
docs.ruby-lang.org
そして検索してたら下記のようなページを発見し、g.yield
と書けそうなことがわかったのでそれを使いました。
qiita.com
Problem 2-3
$s = 0
def say(n = 0)
$s = $s * 4 + n
end
i, j, k = 1, 2, 3
say i
say j
say k
$s != 35 or puts("Hello world")
My Answer(2文字)
$s = 0
def say(n = 0)
$s = $s * 4 + n
end
i, j, k = 1, 2, 3
say i
say j
say k
$s+8 != 35 or puts("Hello world")
$s
が27を返すので、35となるように+8
しました。
Day 3
Problem 3-1
def say s="Hello", t:'world'
"#{ s }#{ t } world"
end
puts say :p
My Answer(1文字)
def say s="Hello", t:'world'
"#{ s }#{ t } world"
end
puts say t:p
p
の返り値はnil
なので、s="Hello", t:nil
となり、"Hello world"が出力されます。
Problem 3-2
def say s, t="Goodbye "
s = "#{ s } #{ t }"
t + "world"
end
puts say :Hello
My Answer(3文字)
def say s, t="Goodbye "
st = "#{ s } "
st + "world"
end
puts say :Hello
ここは最初say :Hello,p
のような形でいけるかと思ったのですが、
:Hello
はsymbolのため+
メソッドが使えないのです。。。
なので、st = "#{ s } "
とすることで、st
に"Hello"だけが入るようにして、
st + "world"
として"Hello world"となるようにしました。
Problem 3-3
def say
"Hello world" if
false && false
end
puts say
My Answer(2文字)
def say
"Hello world" if
:false && :false
end
puts say
これは単純で、false
がtrue
になるようにすればいいので、
!false
と思ったのですが、それだとあまりにもと思ったので:false
にしました。
Ruby Kaigi後に出題されたExtra Stageについてもやってみたので、解答をメモしておきます✍
"Cookpad Daily Ruby Puzzles" in RubyKaigi 2019 - Extra Stage · GitHub
⚠️⚠️⚠️ここからは解答がまだ発表されていないので、ネタバレ注意です⚠️⚠️⚠️
Problem Extra-1
Hello = "Hello"
def Hello
Hello() +
" world"
end
puts Hello()
My Answer(2文字)
Hello = "Hello"
def Hello
Hello+
" world"
end
puts Hello()
これはHintの通り、メソッド呼び出しを止めればいいので、Hello+#() +
として、変数側のHello
を参照するようにしました。
Problem Extra-2
s = ""
s == s.upcase or
s == s.downcase or puts "Hello world"
My Answer(1文字)
s = "Dz"
s == s.upcase or
s == s.downcase or puts "Hello world"
これはHintのURLを参考したら該当文字Dz
が載っていたので、それを使うようにしました。
Problem Extra-3
def say
s = 'Small'
t = 'world'
puts "#{s} #{t}"
end
TracePoint.new(:line){|tp|
tp.binding.local_variable_set(:s, 'Hello')
tp.binding.local_variable_set(:t, 'Ruby')
tp.disable
}.enable(target: method(:say))
say
My Answer(2文字)
def say
s = 'Small'
t = 'world'
puts "#{s} #{t}"
end
TracePoint.new(:line){|tp|
tp.binding.local_variable_set(:s, 'Hello')
}.enable(target: method(:say))
say
tp.disable
をコメントアウトしたところ"Hello Ruby"が返されるようになったので、
tp.binding.local_variable_set(:s, 'Hello')
だけが実行されるようにしました。
おわりに
Cookpadさんの問題が、面白すぎてセッションに集中出来なかった部分もありますが・・・笑
問題に取り組むなかで、マニュアルを読んだり、いろいろ調べたりするなかで、
rubyのイディオムやリテラル周りの知識が見について非常に勉強になりました🙌
来年のRuby Kaigiでは、もっといい感じの答えが出せるように頑張ろう💪