Skip to content

Instantly share code, notes, and snippets.

@esehara
Created December 22, 2016 19:16
Show Gist options
  • Save esehara/f5515d46e3ddc62fd68dd774306e7d5a to your computer and use it in GitHub Desktop.
Save esehara/f5515d46e3ddc62fd68dd774306e7d5a to your computer and use it in GitHub Desktop.
99ソルバー
# 99というダイスゲームとは
#
# ルールとしては、まず目標値を決める。この目標値は33から99となる。
# そして、各プレイヤーはサイコロを5個振る。このサイコロの5個の出目を
# 足し算・引き算・掛け算・割り算を使って、目標値まで近づける。
# 最も目標値に近いプレイヤーが勝つ、というルールのゲーム。
#
# 詳しくは『ダイスゲーム百科』024pを参考にすること。
class Game
attr_accessor :dices_perm, :goal, :temp_answer
OPLIST = ["+", "-", "--", "*", "/", "//"].repeated_permutation(4)
def initialize
@goal = Random.rand(66) + 33
set_dices
end
def set_dices
@dices = Array.new(5) { Random.rand(6) + 1 }
@dices_perm = @dices.permutation(5)
end
def goal_check(result, ops, dices, pattern)
return if result < 0
@temp_answer = [ops, dices, result] if @temp_answer.nil?
if (@goal - @temp_answer[2]).abs > (@goal - result).abs
@temp_answer = [ops, dices, result, pattern]
end
end
def solve
@dices_perm.each do |d|
OPLIST.each do |op|
begin
# 7割は解ける
goal_check(
solve_ops(
solve_op(d[0], d[1], op[0]),
d[2..4].zip(op[1..3])),
d, op, "((((a o1 b) o2 c) o3 d) o4 e)")
break if goal == @temp_answer[2]
# 言うてもそんなに改善はしない
goal_check(
solve_op(
solve_op(
solve_op(d[0], d[1], op[0]),
solve_op(d[2], d[3], op[2]),
op[1]
), d[4], op[3]
),
d, op, "((a o1 b) o2 (c o3 b)) o4 e"
)
rescue ZeroDivisionError
next
end
end
end
end
def to_ans_s
n = @temp_answer[0]
o = @temp_answer[1]
n[0], n[1] = n[1], n[0] if o[0] == "--" || o[0] == "//"
o[0] = '-' if o[0] == "--"
o[0] = '/' if o[0] == "//"
case @temp_answer[3]
when "((((a o1 b) o2 c) o3 d) o4 e)"
a = "(#{n[0]} #{o[0]} #{n[1]})"
n[2..4].zip(o[1..3]).each do |x|
a = create_paren(a, x[0], x[1])
end
when "((a o1 b) o2 (c o3 b)) o4 e"
a = "(#{n[0]} #{o[0]} #{n[1]})"
n[3], n[2] = n[2], n[3] if o[2] == "--" || o[2] == "//"
o[2] = '-' if o[2] == "--"
o[2] = '/' if o[2] == "//"
c = "(#{n[2]} #{o[2]} #{n[3]})"
if o[1] == "--" || o[1] == "//"
o[1] = '-' if o[1] == "--"
o[1] = '/' if o[1] == "//"
b = "(#{c} #{o[1]} #{a})"
else
b = "(#{a} #{o[1]} #{c})"
end
a = create_paren(b, n[4], o[3])
end
"#{a} = #{@temp_answer[2]}"
end
def create_paren(s, n, o)
if o == '--' || o == '//'
o = '-' if o == "--"
o = '/' if o == "//"
"(#{n} #{o} #{s})"
else
"(#{s} #{o} #{n})"
end
end
def solve_op(a, b, o)
case o
when "+"
a + b
when "-"
a - b
when "--"
b - a
when "*"
a * b
when "/"
a / b
when "//"
b / a
end
end
def solve_ops(result, rest)
rest.each do |r|
result = solve_op(result, r[0], r[1])
end
result
end
end
solves = 0
1000.times do
game = Game.new
game.solve
print "GOAL #{game.goal}:"
puts game.to_ans_s
solves += 1 if game.goal == game.temp_answer[2]
end
puts solves
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment