RosettaCodeData/Task/24-game-Solve/Ruby/24-game-solve.rb

42 lines
1.1 KiB
Ruby

class TwentyFourGame
EXPRESSIONS = [
'((%dr %s %dr) %s %dr) %s %dr',
'(%dr %s (%dr %s %dr)) %s %dr',
'(%dr %s %dr) %s (%dr %s %dr)',
'%dr %s ((%dr %s %dr) %s %dr)',
'%dr %s (%dr %s (%dr %s %dr))',
]
OPERATORS = [:+, :-, :*, :/].repeated_permutation(3).to_a
def self.solve(digits)
solutions = []
perms = digits.permutation.to_a.uniq
perms.product(OPERATORS, EXPRESSIONS) do |(a,b,c,d), (op1,op2,op3), expr|
# evaluate using rational arithmetic
text = expr % [a, op1, b, op2, c, op3, d]
value = eval(text) rescue next # catch division by zero
solutions << text.delete("r") if value == 24
end
solutions
end
end
# validate user input
digits = ARGV.map do |arg|
begin
Integer(arg)
rescue ArgumentError
raise "error: not an integer: '#{arg}'"
end
end
digits.size == 4 or raise "error: need 4 digits, only have #{digits.size}"
solutions = TwentyFourGame.solve(digits)
if solutions.empty?
puts "no solutions"
else
puts "found #{solutions.size} solutions, including #{solutions.first}"
puts solutions.sort
end