はじめに
@Kuniwakさんが投稿していた
「これが解けるような秀才は募集しておりません^^」Prolog「まかせろ」を読みました.
この問題自体は解いたことがあったのですがプログラムにしたことはなかったので,自分自身のスキルアップがてら挑戦してみることにしました!
(Rubyマスターでもなんでもないので,こうした方がいい,こう考えた方がいいなどあれば,是非コメントください!)
問題「これが解けるような秀才は募集しておりません^^」
みなみとかおりの二人が数当てゲームをしていて、さやかが横で見ている。
このゲームは二人が1~13のトランプのカードの中から1枚取り、
先に相手の数字を当てた方が勝ちになるもので、みなみとかおりは自分のカードの数字しか見ることはできないが、さやかは二人のカードの数字を見ている。
3人が次の順で会話したとき、みなみとかおりのカードの数字を答えなさい。
さやか「二人のカードは異なる数字で、どちらも1ではない。片方がもう一方の整数倍の数字になっている」
みなみ「うーん、わからない」
かおり「私もわからない」
みなみ「そうか、今わかった」
プログラム
solution.rb
# 「どちらも1ではないわ」ということなので2からスタート
2.upto(12) do |minami_number|
# 「二人のカードは異なる数字」
# 「片方がもう一方の倍数になっているわよ」
# 上記条件に合うかおりのカード候補を取得
candidate_arr = (2..12).select do |kaori_number|
((minami_number % kaori_number).zero? || (kaori_number % minami_number).zero?) && minami_number != kaori_number
end
# 「うーん、わからないわ」
# => kaoriの候補番号が2つ以上ある状況
next if candidate_arr.size < 2
delete_arr = Array.new
candidate_arr.each do |num|
multiple_arr = Array.new
2.upto(12) do |divisor|
next if num == divisor
# kaoriの候補番号の倍数を調べる(1つしかないならkaoriは分かるはず)
if num % divisor == 0 || divisor % num == 0
multiple_arr << divisor
end
end
# 「私もわからないわ」
# => kaoriの候補番号の倍数が1つの場合は「私はわかる」はず
if multiple_arr.size == 1
delete_arr << num
end
end
delete_arr.each do |num|
candidate_arr.delete(num)
end
# 「そうか、いま、わかったわ」
if candidate_arr.size == 1
puts "minami : #{minami_number}"
puts "kaori : #{candidate_arr.first}"
break
end
end
今の自分にはこれが限界のようです…
おわりに
当たり前ですが,本問題では,会話の内容が相手の番号を当てるためのヒント,すなわちプログラム内の条件式となります.
会話の中から条件となる部分を抽出し,プログラムに記述する中で,
「こうやって現実にある問題をプログラムに落とし込んでいくんだなー」と実感しておりました:)
最近,設計に興味を持ち,「エリック・エヴァンスのドメイン駆動設計」を読んでいるのですが,上述した作業がDDDにおける現実の問題をドメインに落とし込む作業に近いんですかね?どうなんですかね?
というわけで,プログラムや最後のDDDっぽいのかな?などの点について,あなたのコメントをお待ちしております!
ありがとうございました.
編集
・2017年12月4日(月) @t2kojima のコメントをもとに修正
修正前
candidate_arr = Array.new
2.upto(12) do |kaori_number|
# 「二人のカードは異なる数字」
next if minami_number == kaori_number
# 「片方がもう一方の倍数になっているわよ」
if minami_number % kaori_number == 0 || kaori_number % minami_number == 0
candidate_arr << kaori_number
end
end
修正後
# 「二人のカードは異なる数字」
# 「片方がもう一方の倍数になっているわよ」
# 上記条件に合うかおりのカード候補を取得
candidate_arr = (2..12).select do |kaori_number|
((minami_number % kaori_number).zero? || (kaori_number % minami_number).zero?) && minami_number != kaori_number
end
他にもArray.newがあるけど…さて,どう消すべきか