上次看到一個“湊24”的題目但想不出來- -b,所以蛋疼地寫了個程式來算。。。現在終於知道答案了。。。
這個湊24程式沒有用搜尋或遞迴之類,想法就是先用逆波蘭式枚舉所有可能的運算式的形式(這個直接手算枚舉),共 5 種:
11+1+1+
11+11++
111++1+
111+1++
1111+++
上面是由 4 個數字和 3 個運算子組成的所有合法的逆波蘭式的模式。“1”表示一個數字,而“+”表示一個運算子。然後枚舉每一個數字和運算子。總枚舉量為:5 * 4! * 4^3 = 7680,枚舉量很小,所以直接窮舉即可。
代碼:
-- 計算逆波蘭式<br />-- (table) -> number<br />function evalPo(e)<br /> local s = {} -- a stack<br /> local a, b, c<br /> for i, v in ipairs(e) do<br /> if type(v) == "number" then<br /> table.insert(s, v)<br /> elseif type(v) == "string" then<br /> if #s < 2 then<br /> error('not enough values')<br /> end<br /> b = table.remove(s)<br /> a = table.remove(s)<br /> if v == '+' then<br /> c = a + b<br /> elseif v == '-' then<br /> c = a - b<br /> elseif v == '*' then<br /> c = a * b<br /> elseif v == '/' then<br /> if b == 0 then<br /> return nil, 'divided by 0'<br /> else<br /> c = a / b<br /> end<br /> else<br /> error('bad operator: '..v)<br /> end<br /> table.insert(s, c)<br /> end<br /> end<br /> if #s ~= 1 then<br /> return nil, 'not enough operators'<br /> end<br /> return s[1]<br />end</p><p>-- 將逆波蘭式轉換成普通運算式,用於輸出<br />-- (table) -> string<br />function RPNtoExp(e)<br /> local s = {} -- a stack<br /> local a, b, c<br /> for i, v in ipairs(e) do<br /> if type(v) == "number" then<br /> table.insert(s, v)<br /> elseif type(v) == "string" then<br /> if #s < 2 then<br /> error('not enough values')<br /> end<br /> b = table.remove(s)<br /> a = table.remove(s)<br /> table.insert(s, '('..a..v..b..')')<br /> end<br /> end<br /> if #s ~= 1 then<br /> return nil, 'not enough operators'<br /> end<br /> return s[1]<br />end</p><p>-- 前4列表示4個數字在逆波蘭式中的位置,後3列表示3個運算子在逆波蘭式中的位置<br />-- 這個表是手算出來的<br />local RPN_patterns = {<br /> {1, 2, 4, 6, 3, 5, 7},<br /> {1, 2, 4, 5, 3, 6, 7},<br /> {1, 2, 3, 6, 4, 5, 7},<br /> {1, 2, 3, 5, 4, 6, 7},<br /> {1, 2, 3, 4, 5, 6, 7}<br />}</p><p>local ar = {}<br />io.write('Please input 4 numbers: ')<br />for i = 1, 4 do<br /> ar[i] = io.read('*n')<br />end</p><p>local operators = {'+', '-', '*', '/'}</p><p>-- 逆波蘭式<br />local exp = {}</p><p>for a = 1, 4 do<br /> for b = 1, 4 do<br /> if b ~= a then<br /> for c = 1, 4 do<br /> if c ~= a and c ~= b then<br /> for d = 1, 4 do<br /> if d ~= a and d ~= b and d ~= c then<br /> for i = 1, 4 do<br /> for j = 1, 4 do<br /> for k = 1, 4 do<br /> for m = 1, 5 do<br /> exp[RPN_patterns[m][1]] = ar[a]<br /> exp[RPN_patterns[m][2]] = ar[b]<br /> exp[RPN_patterns[m][3]] = ar[c]<br /> exp[RPN_patterns[m][4]] = ar[d]<br /> exp[RPN_patterns[m][5]] = operators[i]<br /> exp[RPN_patterns[m][6]] = operators[j]<br /> exp[RPN_patterns[m][7]] = operators[k]<br /> local t = evalPo(exp)<br /> if t == 24 then<br /> io.write(RPNtoExp(exp), '/n')<br /> os.exit()<br /> end<br /> end<br /> end<br /> end<br /> end<br /> end<br /> end<br /> end<br /> end<br /> end<br /> end<br />end<br />print('Maze24 has no idea.')
如果你的電腦上沒有 Lua 解譯器,也可以用 codepad(http://codepad.org/)來線上運行這段代碼。但 codepad 無法輸入,所以你需要稍微修改一下代碼:
把 'Please input 4 numbers: ' 後面的那個 for 迴圈去掉,改成:
ar = {5, 5, 5, 1}
或者填入其他你想要湊 24 的 4 個數字。
PS. 順便附 3 組收藏的湊 24 題目:
1 4 5 6
6 7 -6 2 // 還負數呢,我勒個去
4 4 10 10
如果想不出來,用上面的程式看答案吧:P