from fractions import Fraction
import itertools
# 定义运算符
OPS = ['+', '-', '*', '/']
def apply_op(a, b, op):
"""应用运算符"""
if op == '+':
return a + b
elif op == '-':
return a - b
elif op == '*':
return a * b
elif op == '/':
if b == 0:
return None # 除以零无效
return a / b
def format_expression(a, b, op):
"""格式化两个操作数的表达式,处理交换律"""
# 对于加法和乘法,将操作数排序以处理交换律
if op in ['+', '*']:
a_str = f"({a})" if isinstance(a, str) and ' ' in a else str(a)
b_str = f"({b})" if isinstance(b, str) and ' ' in b else str(b)
# 简单的字符串排序来标准化
if a_str > b_str:
a_str, b_str = b_str, a_str
return f"{a_str} {op} {b_str}"
else:
a_str = f"({a})" if isinstance(a, str) and ' ' in a else str(a)
b_str = f"({b})" if isinstance(b, str) and ' ' in b else str(b)
return f"{a_str} {op} {b_str}"
def solve_24(numbers):
"""主求解函数"""
solutions = set()
# 1. 穷举所有数字的排列
for p in itertools.permutations(numbers):
a, b, c, d = [Fraction(n) for n in p]
# 2. 穷举所有运算符的组合
for op1 in OPS:
for op2 in OPS:
for op3 in OPS:
ops = [op1, op2, op3]
# 3. 穷举所有五种括号结构
# 结构1: ((a op1 b) op2 c) op3 d
try:
res1 = apply_op(a, b, op1)
if res1 is not None:
res2 = apply_op(res1, c, op2)
if res2 is not None:
res3 = apply_op(res2, d, op3)
if res3 is not None and res3 == 24:
expr = format_expression(a, b, op1)
expr = format_expression(expr, c, op2)
expr = format_expression(expr, d, op3)
solutions.add(expr)
except:
pass
# 结构2: (a op1 (b op2 c)) op3 d
try:
res1 = apply_op(b, c, op2)
if res1 is not None:
res2 = apply_op(a, res1, op1)
if res2 is not None:
res3 = apply_op(res2, d, op3)
if res3 is not None and res3 == 24:
inner_expr = format_expression(b, c, op2)
expr = format_expression(a, inner_expr, op1)
expr = format_expression(expr, d, op3)
solutions.add(expr)
except:
pass
# 结构3: a op1 ((b op2 c) op3 d)
try:
res1 = apply_op(b, c, op2)
if res1 is not None:
res2 = apply_op(res1, d, op3)
if res2 is not None:
res3 = apply_op(a, res2, op1)
if res3 is not None and res3 == 24:
inner_expr1 = format_expression(b, c, op2)
inner_expr2 = format_expression(inner_expr1, d, op3)
expr = format_expression(a, inner_expr2, op1)
solutions.add(expr)
except:
pass
# 结构4: a op1 (b op2 (c op3 d))
try:
res1 = apply_op(c, d, op3)
if res1 is not None:
res2 = apply_op(b, res1, op2)
if res2 is not None:
res3 = apply_op(a, res2, op1)
if res3 is not None and res3 == 24:
inner_expr1 = format_expression(c, d, op3)
inner_expr2 = format_expression(b, inner_expr1, op2)
expr = format_expression(a, inner_expr2, op1)
solutions.add(expr)
except:
pass
# 结构5: (a op1 b) op2 (c op3 d)
try:
res1 = apply_op(a, b, op1)
res2 = apply_op(c, d, op3)
if res1 is not None and res2 is not None:
res3 = apply_op(res1, res2, op2)
if res3 is not None and res3 == 24:
expr1 = format_expression(a, b, op1)
expr2 = format_expression(c, d, op3)
# 对于结构5,op2也可能是+或*,需要整体排序
final_expr = format_expression(expr1, expr2, op2)
solutions.add(final_expr)
except:
pass
return list(solutions)
def main():
"""主函数,处理输入输出"""
try:
# 输入处理
print("请输入4个正整数(小于20),用空格分隔:")
nums = list(map(int, input().split()))
if len(nums) != 4 or any(n <= 0 or n >= 20 for n in nums):
print("输入无效,请输入4个1到19之间的正整数。")
return
solutions = solve_24(nums)
if not solutions:
print("No solution")
else:
# 为了输出顺序一致,对解进行排序
solutions.sort()
for sol in solutions:
# 将分数转换为更易读的格式
formatted_sol = sol.replace('Fraction(', '').replace(')', '')
print(formatted_sol)
except (ValueError, IndexError):
print("输入格式错误,请确保输入了4个数字。")
if __name__ == "__main__":
main()
ZnJvbSBmcmFjdGlvbnMgaW1wb3J0IEZyYWN0aW9uCmltcG9ydCBpdGVydG9vbHMKCiMg5a6a5LmJ6L+Q566X56ymCk9QUyA9IFsnKycsICctJywgJyonLCAnLyddCgpkZWYgYXBwbHlfb3AoYSwgYiwgb3ApOgogICAgIiIi5bqU55So6L+Q566X56ymIiIiCiAgICBpZiBvcCA9PSAnKyc6CiAgICAgICAgcmV0dXJuIGEgKyBiCiAgICBlbGlmIG9wID09ICctJzoKICAgICAgICByZXR1cm4gYSAtIGIKICAgIGVsaWYgb3AgPT0gJyonOgogICAgICAgIHJldHVybiBhICogYgogICAgZWxpZiBvcCA9PSAnLyc6CiAgICAgICAgaWYgYiA9PSAwOgogICAgICAgICAgICByZXR1cm4gTm9uZSAgIyDpmaTku6Xpm7bml6DmlYgKICAgICAgICByZXR1cm4gYSAvIGIKCmRlZiBmb3JtYXRfZXhwcmVzc2lvbihhLCBiLCBvcCk6CiAgICAiIiLmoLzlvI/ljJbkuKTkuKrmk43kvZzmlbDnmoTooajovr7lvI/vvIzlpITnkIbkuqTmjaLlvosiIiIKICAgICMg5a+55LqO5Yqg5rOV5ZKM5LmY5rOV77yM5bCG5pON5L2c5pWw5o6S5bqP5Lul5aSE55CG5Lqk5o2i5b6LCiAgICBpZiBvcCBpbiBbJysnLCAnKiddOgogICAgICAgIGFfc3RyID0gZiIoe2F9KSIgaWYgaXNpbnN0YW5jZShhLCBzdHIpIGFuZCAnICcgaW4gYSBlbHNlIHN0cihhKQogICAgICAgIGJfc3RyID0gZiIoe2J9KSIgaWYgaXNpbnN0YW5jZShiLCBzdHIpIGFuZCAnICcgaW4gYiBlbHNlIHN0cihiKQogICAgICAgICMg566A5Y2V55qE5a2X56ym5Liy5o6S5bqP5p2l5qCH5YeG5YyWCiAgICAgICAgaWYgYV9zdHIgPiBiX3N0cjoKICAgICAgICAgICAgYV9zdHIsIGJfc3RyID0gYl9zdHIsIGFfc3RyCiAgICAgICAgcmV0dXJuIGYie2Ffc3RyfSB7b3B9IHtiX3N0cn0iCiAgICBlbHNlOgogICAgICAgIGFfc3RyID0gZiIoe2F9KSIgaWYgaXNpbnN0YW5jZShhLCBzdHIpIGFuZCAnICcgaW4gYSBlbHNlIHN0cihhKQogICAgICAgIGJfc3RyID0gZiIoe2J9KSIgaWYgaXNpbnN0YW5jZShiLCBzdHIpIGFuZCAnICcgaW4gYiBlbHNlIHN0cihiKQogICAgICAgIHJldHVybiBmInthX3N0cn0ge29wfSB7Yl9zdHJ9IgoKZGVmIHNvbHZlXzI0KG51bWJlcnMpOgogICAgIiIi5Li75rGC6Kej5Ye95pWwIiIiCiAgICBzb2x1dGlvbnMgPSBzZXQoKQogICAgCiAgICAjIDEuIOept+S4vuaJgOacieaVsOWtl+eahOaOkuWIlwogICAgZm9yIHAgaW4gaXRlcnRvb2xzLnBlcm11dGF0aW9ucyhudW1iZXJzKToKICAgICAgICBhLCBiLCBjLCBkID0gW0ZyYWN0aW9uKG4pIGZvciBuIGluIHBdCiAgICAgICAgCiAgICAgICAgIyAyLiDnqbfkuL7miYDmnInov5DnrpfnrKbnmoTnu4TlkIgKICAgICAgICBmb3Igb3AxIGluIE9QUzoKICAgICAgICAgICAgZm9yIG9wMiBpbiBPUFM6CiAgICAgICAgICAgICAgICBmb3Igb3AzIGluIE9QUzoKICAgICAgICAgICAgICAgICAgICBvcHMgPSBbb3AxLCBvcDIsIG9wM10KICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAjIDMuIOept+S4vuaJgOacieS6lOenjeaLrOWPt+e7k+aehAogICAgICAgICAgICAgICAgICAgICMg57uT5p6EMTogKChhIG9wMSBiKSBvcDIgYykgb3AzIGQKICAgICAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgICAgIHJlczEgPSBhcHBseV9vcChhLCBiLCBvcDEpCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczEgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMyID0gYXBwbHlfb3AocmVzMSwgYywgb3AyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgcmVzMiBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMzID0gYXBwbHlfb3AocmVzMiwgZCwgb3AzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczMgaXMgbm90IE5vbmUgYW5kIHJlczMgPT0gMjQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHIgPSBmb3JtYXRfZXhwcmVzc2lvbihhLCBiLCBvcDEpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHIgPSBmb3JtYXRfZXhwcmVzc2lvbihleHByLCBjLCBvcDIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHIgPSBmb3JtYXRfZXhwcmVzc2lvbihleHByLCBkLCBvcDMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvbHV0aW9ucy5hZGQoZXhwcikKICAgICAgICAgICAgICAgICAgICBleGNlcHQ6CiAgICAgICAgICAgICAgICAgICAgICAgIHBhc3MKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAjIOe7k+aehDI6IChhIG9wMSAoYiBvcDIgYykpIG9wMyBkCiAgICAgICAgICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgICAgICAgICByZXMxID0gYXBwbHlfb3AoYiwgYywgb3AyKQogICAgICAgICAgICAgICAgICAgICAgICBpZiByZXMxIGlzIG5vdCBOb25lOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzMiA9IGFwcGx5X29wKGEsIHJlczEsIG9wMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczIgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzMyA9IGFwcGx5X29wKHJlczIsIGQsIG9wMykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiByZXMzIGlzIG5vdCBOb25lIGFuZCByZXMzID09IDI0OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbm5lcl9leHByID0gZm9ybWF0X2V4cHJlc3Npb24oYiwgYywgb3AyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHByID0gZm9ybWF0X2V4cHJlc3Npb24oYSwgaW5uZXJfZXhwciwgb3AxKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHByID0gZm9ybWF0X2V4cHJlc3Npb24oZXhwciwgZCwgb3AzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb2x1dGlvbnMuYWRkKGV4cHIpCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgICAgICAgICBwYXNzCgogICAgICAgICAgICAgICAgICAgICMg57uT5p6EMzogYSBvcDEgKChiIG9wMiBjKSBvcDMgZCkKICAgICAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgICAgIHJlczEgPSBhcHBseV9vcChiLCBjLCBvcDIpCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczEgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMyID0gYXBwbHlfb3AocmVzMSwgZCwgb3AzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgcmVzMiBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMzID0gYXBwbHlfb3AoYSwgcmVzMiwgb3AxKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczMgaXMgbm90IE5vbmUgYW5kIHJlczMgPT0gMjQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlubmVyX2V4cHIxID0gZm9ybWF0X2V4cHJlc3Npb24oYiwgYywgb3AyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbm5lcl9leHByMiA9IGZvcm1hdF9leHByZXNzaW9uKGlubmVyX2V4cHIxLCBkLCBvcDMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHIgPSBmb3JtYXRfZXhwcmVzc2lvbihhLCBpbm5lcl9leHByMiwgb3AxKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb2x1dGlvbnMuYWRkKGV4cHIpCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgICAgICAgICBwYXNzCgogICAgICAgICAgICAgICAgICAgICMg57uT5p6ENDogYSBvcDEgKGIgb3AyIChjIG9wMyBkKSkKICAgICAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgICAgIHJlczEgPSBhcHBseV9vcChjLCBkLCBvcDMpCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczEgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMyID0gYXBwbHlfb3AoYiwgcmVzMSwgb3AyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgcmVzMiBpcyBub3QgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMzID0gYXBwbHlfb3AoYSwgcmVzMiwgb3AxKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczMgaXMgbm90IE5vbmUgYW5kIHJlczMgPT0gMjQ6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlubmVyX2V4cHIxID0gZm9ybWF0X2V4cHJlc3Npb24oYywgZCwgb3AzKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbm5lcl9leHByMiA9IGZvcm1hdF9leHByZXNzaW9uKGIsIGlubmVyX2V4cHIxLCBvcDIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHIgPSBmb3JtYXRfZXhwcmVzc2lvbihhLCBpbm5lcl9leHByMiwgb3AxKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb2x1dGlvbnMuYWRkKGV4cHIpCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgICAgICAgICBwYXNzCgogICAgICAgICAgICAgICAgICAgICMg57uT5p6ENTogKGEgb3AxIGIpIG9wMiAoYyBvcDMgZCkKICAgICAgICAgICAgICAgICAgICB0cnk6CiAgICAgICAgICAgICAgICAgICAgICAgIHJlczEgPSBhcHBseV9vcChhLCBiLCBvcDEpCiAgICAgICAgICAgICAgICAgICAgICAgIHJlczIgPSBhcHBseV9vcChjLCBkLCBvcDMpCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlczEgaXMgbm90IE5vbmUgYW5kIHJlczIgaXMgbm90IE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXMzID0gYXBwbHlfb3AocmVzMSwgcmVzMiwgb3AyKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgcmVzMyBpcyBub3QgTm9uZSBhbmQgcmVzMyA9PSAyNDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHByMSA9IGZvcm1hdF9leHByZXNzaW9uKGEsIGIsIG9wMSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHByMiA9IGZvcm1hdF9leHByZXNzaW9uKGMsIGQsIG9wMykKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIOWvueS6jue7k+aehDXvvIxvcDLkuZ/lj6/og73mmK8r5oiWKu+8jOmcgOimgeaVtOS9k+aOkuW6jwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbmFsX2V4cHIgPSBmb3JtYXRfZXhwcmVzc2lvbihleHByMSwgZXhwcjIsIG9wMikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb2x1dGlvbnMuYWRkKGZpbmFsX2V4cHIpCiAgICAgICAgICAgICAgICAgICAgZXhjZXB0OgogICAgICAgICAgICAgICAgICAgICAgICBwYXNzCgogICAgcmV0dXJuIGxpc3Qoc29sdXRpb25zKQoKZGVmIG1haW4oKToKICAgICIiIuS4u+WHveaVsO+8jOWkhOeQhui+k+WFpei+k+WHuiIiIgogICAgdHJ5OgogICAgICAgICMg6L6T5YWl5aSE55CGCiAgICAgICAgcHJpbnQoIuivt+i+k+WFpTTkuKrmraPmlbTmlbDvvIjlsI/kuo4yMO+8ie+8jOeUqOepuuagvOWIhumalDoiKQogICAgICAgIG51bXMgPSBsaXN0KG1hcChpbnQsIGlucHV0KCkuc3BsaXQoKSkpCiAgICAgICAgCiAgICAgICAgaWYgbGVuKG51bXMpICE9IDQgb3IgYW55KG4gPD0gMCBvciBuID49IDIwIGZvciBuIGluIG51bXMpOgogICAgICAgICAgICBwcmludCgi6L6T5YWl5peg5pWI77yM6K+36L6T5YWlNOS4qjHliLAxOeS5i+mXtOeahOato+aVtOaVsOOAgiIpCiAgICAgICAgICAgIHJldHVybgogICAgICAgICAgICAKICAgICAgICBzb2x1dGlvbnMgPSBzb2x2ZV8yNChudW1zKQogICAgICAgIAogICAgICAgIGlmIG5vdCBzb2x1dGlvbnM6CiAgICAgICAgICAgIHByaW50KCJObyBzb2x1dGlvbiIpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgIyDkuLrkuobovpPlh7rpobrluo/kuIDoh7TvvIzlr7nop6Pov5vooYzmjpLluo8KICAgICAgICAgICAgc29sdXRpb25zLnNvcnQoKQogICAgICAgICAgICBmb3Igc29sIGluIHNvbHV0aW9uczoKICAgICAgICAgICAgICAgICMg5bCG5YiG5pWw6L2s5o2i5Li65pu05piT6K+755qE5qC85byPCiAgICAgICAgICAgICAgICBmb3JtYXR0ZWRfc29sID0gc29sLnJlcGxhY2UoJ0ZyYWN0aW9uKCcsICcnKS5yZXBsYWNlKCcpJywgJycpCiAgICAgICAgICAgICAgICBwcmludChmb3JtYXR0ZWRfc29sKQogICAgICAgICAgICAgICAgCiAgICBleGNlcHQgKFZhbHVlRXJyb3IsIEluZGV4RXJyb3IpOgogICAgICAgIHByaW50KCLovpPlhaXmoLzlvI/plJnor6/vvIzor7fnoa7kv53ovpPlhaXkuoY05Liq5pWw5a2X44CCIikKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBtYWluKCk=