前段时间琢磨着教儿子打牌。后来牌买了,又考虑先学那种玩法呢。大众的玩法都需要两三个人的,而且规则也比较复杂。我于是想,先玩24点吧,就是随机抽取4张牌,用牌面的数字和加减乘除运算组合起来,计算出24这个数字。儿子开始还很兴奋,玩了两把就发现我还是在骗他算算数,于是就彻底失去了兴趣。
话说24点我的水平还行,但偶尔遇到依稀数字组合还是挺难的。我就想,编程计算好了。我开始考虑的就是先考虑两个数字,加减乘除能得到最多6个结果,然后递归,再增加一个数字,得到所有三个数字结果,再递归加一个数字得到所有4个数字可能的结果。程序几行就够了。编完才发现,这种递归方法遗漏了一种情况,就是4个数字必须先俩俩算完,然后再最后得到结果的,比如(1+2)*(1+7)这种。再考虑这种情况就写不出特别简介优美的递归了 :(
这是个简单递归程序,可以应付大多数问题:
from typing import List
Operators = {
"+": lambda a, t : t - a,
"-": lambda a, t : a - t,
"*": lambda a, t : None if a == 0 else t / a,
"/": lambda a, t : None if t == 0 else a / t,
}
def calculate(numbers: List[int], target: float, message: str):
if len(numbers) == 1:
if numbers[0] == target:
print(message[:-1] + str(numbers[0]) + "))")
else:
pass
else:
for num in set(numbers):
numbers.remove(num)
for operator, solve in Operators.items():
calculate (numbers, solve(num, target), message + str(num) + operator + "(")
numbers.append(num)
print(calculate([3,3,8,8], 24, ''))
一个复杂的程序穷举所有可能:
from typing import List
from copy import deepcopy
from math import nan
Operators = {
"+": lambda a, b : a + b,
"*": lambda a, b : a * b,
}
Order_Operators = {
"-": lambda a, b : a - b,
"/": lambda a, b : nan if b == 0 else a / b,
}
Target = 24
def print_result(a_value: float, a_string: str, b_value: float, b_string: str):
for operator, solve in Operators.items():
if abs(solve(a_value, b_value) - Target) < 0.001:
print(a_string + operator + b_string)
for operator, solve in Order_Operators.items():
if abs(solve(a_value, b_value) - Target) < 0.001:
print(a_string + operator + b_string)
if abs(solve(b_value, a_value) - Target) < 0.001:
print(b_string + operator + a_string)
def all_1_3_groups(numbers: List[int]):
groups = {}
groups[numbers[0]] = numbers[1:]
groups[numbers[1]] = [numbers[0]] + numbers[2:]
groups[numbers[2]] = numbers[0:2] + [numbers[3]]
groups[numbers[3]] = numbers[:-1]
return groups
def all_2_2_groups(numbers: List[int]):
groups = []
processed = set()
groups.append([(numbers[0], numbers[1]), (numbers[2], numbers[3])])
processed.add((numbers[0], numbers[1]))
processed.add((numbers[2], numbers[3]))
if (numbers[0], numbers[1]) not in processed:
groups.append([(numbers[0], numbers[2]), (numbers[1], numbers[3])])
processed.add((numbers[0], numbers[2]))
processed.add((numbers[1], numbers[3]))
if (numbers[0], numbers[3]) not in processed:
groups.append([(numbers[0], numbers[3]), (numbers[1], numbers[2])])
return groups
def process_2_operands (a_value: float, a_string: str, b_value: float, b_string: str):
results = []
for operator, solve in Operators.items():
results.append((solve(a_value, b_value), "(" + a_string + operator + b_string + ")"))
for operator, solve in Order_Operators.items():
results.append((solve(a_value, b_value), "(" + a_string + operator + b_string + ")"))
results.append((solve(b_value, a_value), "(" + b_string + operator + a_string + ")"))
return results
def process_3_operands(numbers_3: List[int]):
results = []
for num in set(numbers_3):
numbers = deepcopy(numbers_3)
numbers.remove(num)
results_2_operands = process_2_operands(numbers[0], str(numbers[0]), numbers[1], str(numbers[1]))
for result_2 in results_2_operands:
results += process_2_operands(num, str(num), result_2[0], result_2[1])
return results
def process_4_operands(numbers: List[int]):
groups_1_3 = all_1_3_groups(numbers)
for num, others in groups_1_3.items():
results_3_operands = process_3_operands(others)
for result_3 in results_3_operands:
print_result(num, str(num), result_3[0], result_3[1])
groups_2_2 = all_2_2_groups(numbers)
for group in groups_2_2:
results_a = process_2_operands(group[0][0], str(group[0][0]), group[0][1], str(group[0][1]))
results_b = process_2_operands(group[1][0], str(group[1][0]), group[1][1], str(group[1][1]))
for a in results_a:
for b in results_b:
print_result(a[0], a[1], b[0], b[1])
print("Done.")
print(process_4_operands([1,2,1,7]))
No comments:
Post a Comment