算 24 点

 

问题

算 24 点游戏是一种经典的用扑克牌来进行的益智游戏。游戏内容是:从一副扑克牌中抽去大小王剩下 52 张,任意抽取 4 张牌,把牌面上的数字(J、Q、K、A 分别代表 11、12、13、1)运用加、减、乘、除和括号进行运算得出 24。每张牌都必须使用一次,但不能重复使用。

请编写代码对任意给出的四张牌算 24 点,用文本输出解答,如果无解则输出“无解”。

思路

  1. 将 4 个数字按照不同的顺序进行排列

  2. 在 1 的循环中,将 4 个运算符取其中三个并且按照不同的方式进行排列

  3. 在 2 的循环中,将三个符号添加到四个数字之间

  4. 枚举了以下 5 种括号情况分别计算(其中 A,B,C,D 表示数字,# 表示不同的符号):

  • ((A#B)#C)#D
  • (A#(B#C))#D
  • (A#B)#(C#D)
  • A#((B#C)#D)
  • A#(B#(C#D))

代码

A B C D
1 [3,3,8,8]
2 [1234,1243,1324,1342,1423,1432,2134,2143,2314,2341,2413,2431,3124,3142,3214,3241,3412,3421,4123,4132,4213,4231,4312,4321]
3 for A2 =A1(4.(int(A3/power(10,4-#))%10)) 将 A1 中的成员按照 A2 排列
4 for 64 在 +,_,*,/ 四个运算符中取任意 3 个,可以相同,因此每一个都有四种选择,相当于 4×4×4,等于 64 种
5 =["+","-","*","/"](3.(int((B4-1)/power(4,3-#))%4+1)) 把循环序号转成四进制数且每位加 1,即为当前的运算符选法
6 >a=B3(1),b=B3(2),c=B3(3),d=B3(4),x=C5(1),y=C5(2),z=C5(3)
7 =func(A28,[x,a,func(A28,[y,b,func(A28,[z,c,d])])]) 给表达式添加括号,该表达式为 A#(B#(C#D)),然后调用子程序进行计算
8 if abs(C7-24)<0.0001
9 =string(a)+x+"("+string(b)+y+"("+string(c)+z+string(d)+"))"
10 =D10|D9 如果表达式的值等于 24,存储结果
11 =func(A28,[x,a,func(A28,[z,func(A28,[y,b,c]),d])]) 给表达式添加括号,该表达式为 A#((B#C)#D),然后调用子程序进行计算
12 if abs(C11-24)<0.0001
13 =string(a)+x+"(("+string(b)+y+ string(c)+")"+z+string(d)+")"
14 =D14|D13 如果表达式的值等于 24,存储结果
15 =func(A28,[y,func(A28,[x,a,b]),func(A28,[z,c,d])]) 给表达式添加括号,该表达式为 (A#B)#(C#D),然后调用子程序进行计算
16 if abs(C15-24)<0.0001
17 ="("+string(a)+x+string(b)+")"+y+"("+string(c)+z+string(d)+")"
18 =D18|D17 如果表达式的值等于 24,存储结果
19 =func(A28,[z,func(A28,[y,func(A28,[x,a,b]),c]),d]) 给表达式添加括号,该表达式为 ((A#B)#C)#D,然后调用子程序进行计算
20 if abs(C19-24)<0.0001
21 ="(("+string(a)+x+string(b)+")"+y+string(c)+")"+z+string(d)
22 =D22|D21 如果表达式的值等于 24,存储结果
23 =func(A28,[z,func(A28,[x,a,func(A28,[y,b,c])]),d]) 给表达式添加括号,该表达式为 (A#(B#C))#D,然后调用子程序进行计算
24 if abs(C23-24)<0.0001
25 ="("+string(a)+x+"("+string(b)+y+string(c)+"))"+z+string(d)
26 =D26|D25 如果表达式的值等于 24,存储结果
27 =[D10,D14,D18,D22,D26].union().id() 运算结果
28 func 三个参数,第一个参数是运算符,第二个参数是左操作数,第三个参数是右操作数
29 if A28(1)=="+" return A28(2)+A28(3)
30 if A28(1)=="-" return A28(2)-A28(3)
31 if A28(1)=="*" return A28(2)*A28(3)
32 if A28(1)=="/" return A28(2)/A28(3)

结果

imagepng