Bootstrap

24点计算器Ruby脚本

找到的答案比网上的一些工具找到的个数要少,不过可能是臃肿的化简过程中剔除了,因此不保证解的个数正确,不过能找到至少存在解,记录之。

#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


;