找到的答案比网上的一些工具找到的个数要少,不过可能是臃肿的化简过程中剔除了,因此不保证解的个数正确,不过能找到至少存在解,记录之。
#encoding:GBK
require 'set'
num = [4, 2, 9, 6]
ops = ['+', '-', '*', '/']
def simplest(expr)
exprstack = Array.new
exprstack.push(expr)
orgeval = eval(expr)
regexpr1 = Regexp.new(/\(([^\(\)]*|(.*\(.*\).*))\)/)
regexpr2 = Regexp.new(/\(([^\(\)]*)\)/)
regexpr3 = Regexp.new(/\((.*)\)(.*)\((.*)\)/)
newexpr = expr
while newexpr =~ regexpr1
newexpr = newexpr.sub(regexpr1,'\1')
exprstack.push(newexpr)
end
newexpr = expr
while newexpr =~ regexpr2
newexpr = newexpr.sub(regexpr2,'\1')
exprstack.push(newexpr)
end
newexpr = expr
if m = newexpr.match(regexpr3) then
exprstack.push('(' + m[1] + ')' + m[2] + m[3])
exprstack.push(m[1] + m[2] + '(' + m[3] + ')')
exprstack.push(m[1] + m[2] + m[3])
end
exprstack.sort do |a,b|
if a.size > b.size then
-1
elsif a.size == b.size then
0
else
1
end
end
while e = exprstack.pop
if (eval(e) - orgeval).abs < 1e-10
return e
end
end
return expr
end
def calcstr(subarr,op1,op2,op3,prior)
fmtstr = '%f %s %f %s %f %s %f'
if prior == [0,1,2] then
fmtstr = '%f %s (%f %s (%f %s %f))'
elsif prior == [0,2,1] then
fmtstr = '%f %s ((%f %s %f) %s %f)'
elsif prior == [1,0,2] then
fmtstr = '(%f %s %f) %s (%f %s %f)'
elsif prior == [1,2,0] then
fmtstr = '(%f %s (%f %s %f)) %s %f'
elsif prior == [2,0,1] then
fmtstr = '(%f %s %f) %s (%f %s %f)'
elsif prior == [2,1,0] then
fmtstr = '((%f %s %f) %s %f) %s %f'
end
format(fmtstr,subarr[0].to_f,op1,subarr[1].to_f,op2,subarr[2].to_f,op3,subarr[3].to_f)
end
answer = Set.new
num.permutation.each do |subarr|
ops.each do |op1|
ops.each do |op2|
ops.each do |op3|
[0,1,2].permutation.each do |prior|
str = calcstr(subarr,op1,op2,op3,prior)
if (eval(str) - 24.0).abs < 1e-10 then
simplestr = simplest(str)
answer << simplestr.gsub(/\.[0]+/,'').gsub(/[ ]+/,'')
end
end
end
end
end
end
puts "区分相同数字和符号顺序拟#{answer.size}种解法"
answer.each do |a|
puts '我答24点 ' + a
end