【Ruby】【アルゴリズム】10パズルを解く。ファイナルアンサー。回答全部入り。
振り返り。テンパズルとは。
1から9までの、1桁の数字がかかれたカードが4枚ある。
この数字をそれぞれ1回ずつ使い、10になるように計算する。
あれです。
駅の切符とか、ナンバープレートとかで暇つぶしにやるあれ。
方法
1.計算順序を考えるのは大変なので、逆ポーランド記法でパターンを列挙する
⇒この記事でやりました
2.逆ポーランド記法を計算するメソッドを作る
⇒この記事でやりました
3.4つの数の組み合わせを列挙するメソッドを作る
⇒この記事でやりました
ここまできたらあとは計算するだけなので、先が見えています。
ポイント
0で割り算するとinfinityとなり、to_iメソッドを呼び出すとエラーになります。
0で割り算するときは答えが0になると定義しました。
コード
class Calc
def self.make_expression(str)
@@data = str.split("")
@@operatars = ["+","-","*","/"]
_make_rpn([], [], [0,0,0,0], 0, 0)
end
def self._make_rpn(result, candidate, is_uesd, num_count, ope_count)
return result << candidate.join('') if num_count+ope_count == 7
return if num_count+ope_count > 7
if num_count - ope_count >=2
@@operatars.each do |ope|
tmp = candidate.dup
tmp << ope
self._make_rpn(result, tmp, is_uesd, num_count, ope_count + 1)
end
end
if num_count < 4
is_uesd.each_with_index do |isused, idx|
if isused == 0
tmp = is_uesd.dup
tmp2 = candidate.dup
tmp[idx] = 1
tmp2 << @@data[idx]
_make_rpn(result, tmp2, tmp, num_count + 1, ope_count)
end
end
end
result
end
def self.exe(str)
num_stack = []
datas = str.split("")
datas.each do |data|
if data =~ /\d/
num_stack << data
else
a = num_stack.pop
b = num_stack.pop
tmp = _calc(b, a, data)
if tmp
num_stack << tmp
else
return "0"
end
end
end
raise "argument is not correct" if num_stack.length != 1
num_stack[0]
end
def self._calc(num1, num2, operator)
raise "argument is not correct" if num1.nil? || num2.nil?
a = num1.to_f ; b = num2.to_f
return a + b if operator == "+"
return a - b if operator == "-"
return a * b if operator == "*"
if operator == "/"
return a / b if b !=0
return false
end
end
end
candidates = Calc.make_expression("1234")
answers = []
candidates.each do |cand|
answers << cand if Calc.exe(cand).to_i == 10
end
p "there are #{answers.length} answers"
p answers
■実行結果
"there are 48 answers" ["99*9+9/", "99*9+9/", "999*+9/", "999*+9/", "99*9+9/", "99*9+9
この答えの数から、難易度の高い組み合わせを見つけられそうですね。
「最も難しいテンパズル」。
面白そうだけどそこまで興味がないので見送ります。
と思ったけど、ついでなので全回答を作りました。
https://gist.github.com/sekaiya/6569856/
これで切符をニヤニヤみるような彼氏が出来ても、
このgistにアクセスすれば、
あ、9999?。答えは48個あるみたいだね。
ってすぐに会話が終わっちゃう。
っていうかそんな辛気臭い彼氏要らんわ。
やった!
飲んでくる!