24点游戏是一种很常见的数学小游戏。
给定 4 个数字,比如 3、3、8、8,要求你使用加、减、乘、除和括号,把它们组合成 24。
很多时候,孩子们玩 24 点,往往只能想到一种做法,或者卡在“好像有解,但就是想不出来”的状态。此时就会出现两个很自然的问题:
这就非常适合用“穷举搜索”来解决。
计算24点就是四个数的数学计算公式。
因此考虑到穷举搜索,主要有三个变化点:
24 点的穷举一般分成三个层次:
其中最关键的是括号结构,因为加减乘除并不是随便连起来就行,括号会改变运算顺序。
对于 4 个数 数1, 数2, 数3, 数4,3个操作符 操作1, 操作2, 操作3,常见的括号结构有 5 种:
我们把 24 点问题拆成三个嵌套的步骤:
+、-、*、/ 的所有组合都试一遍如果某个表达式结果等于 24,就把它记录下来.
下面给出一个穷举版的 24 点求解程序。它会:
# itertools 是 Python 内置的一个非常有用的模块,提供了很多处理迭代器的函数。
# permutations() 用于生成一个序列的所有排列
# product() 用于生成笛卡尔积,类似于嵌套循环
from itertools import permutations, product
# 1. 定义运算符
OPS = ["+", "-", "*", "/"]
#定义函数实现permutations(nums)后去重
defunique_permutations(nums):
"""生成 nums 的所有唯一排列,返回列表,不使用yield"""
# 用 set() 去重,避免重复排列
seen = set()
# 生成所有排列
result = []
for p in permutations(nums):
if p notin seen:
# 记录已经见过的排列
seen.add(p)
# 把这个排列加入结果列表
result.append(p)
# 返回所有唯一排列
return result
# 2. 定义整数运算函数
# 这个函数只允许整除的除法,如果除不尽就返回 None
# and b 是两个整数,op 是运算符
defcalc_int(a, b, op):
"""整数运算:只有整除时才允许做除法,否则返回 None。"""
if a isNoneor b isNone:
returnNone
if op == "+":
return a + b
if op == "-":
return a - b
if op == "*":
return a * b
if op == "/":
if b == 0: # 避免除以零
returnNone
if a % b != 0: # 只允许整除
returnNone
return a // b # 整除
returnNone
# 3. 找出所有满足“每一步都为整数”的 24 点表达式
defsolve_24_int_only(nums):
"""找出所有满足“每一步都为整数”的 24 点表达式。"""
# 先用 set() 去重,避免重复表达式
solutions = set()
# 枚举所有数字排列
for a, b, c, d in unique_permutations(nums):
# 枚举所有运算符组合
for op1, op2, op3 in product(OPS, repeat=3):
# 5 种括号结构的计算结果
expr_values = []
# 1. ((a op1 b) op2 c) op3 d
x1 = calc_int(a, b, op1)
x2 = calc_int(x1, c, op2)
x3 = calc_int(x2, d, op3)
expr_values.append((f"(({a}{op1}{b}){op2}{c}){op3}{d}", x3))
# 2. (a op1 (b op2 c)) op3 d
y1 = calc_int(b, c, op2)
y2 = calc_int(a, y1, op1)
y3 = calc_int(y2, d, op3)
expr_values.append((f"({a}{op1}({b}{op2}{c})){op3}{d}", y3))
# 3. a op1 ((b op2 c) op3 d)
z1 = calc_int(b, c, op2)
z2 = calc_int(z1, d, op3)
z3 = calc_int(a, z2, op1)
expr_values.append((f"{a}{op1}(({b}{op2}{c}){op3}{d})", z3))
# 4. a op1 (b op2 (c op3 d))
p1 = calc_int(c, d, op3)
p2 = calc_int(b, p1, op2)
p3 = calc_int(a, p2, op1)
expr_values.append((f"{a}{op1}({b}{op2}({c}{op3}{d}))", p3))
# 5. (a op1 b) op2 (c op3 d)
q1 = calc_int(a, b, op1)
q2 = calc_int(c, d, op3)
q3 = calc_int(q1, q2, op2)
expr_values.append((f"({a}{op1}{b}){op2}({c}{op3}{d})", q3))
# 检查每个表达式的结果是否等于 24,如果是,就加入解集
for expr, value in expr_values:
if value == 24:
solutions.add(expr)
return solutions
# 运行示例
nums = [3, 3, 3, 3]
# 运行穷举搜索,找出所有满足“每一步都为整数”的 24 点表达式
solutions = solve_24_int_only(nums)
print("输入数字:", nums)
print("解法数量(全程整数):", len(solutions))
for expr in sorted(solutions):
print(expr)
以 3、3、3、3 为例,程序会找出所有能得到 24 的表达式。
输入数字: [3, 3, 3, 3]
解法数量(全程整数): 2
((3*3)*3)-3
(3*(3*3))-3