如何用Python组合数字、运算符与函数生成所有合法表达式?
解决方案:生成数字、运算符与函数的组合表达式
要实现数字(不重复使用)、运算符(可重复)、函数的嵌套/组合表达式生成,核心是通过递归方式覆盖所有可能的表达式结构(纯数字、运算表达式、函数作用于表达式),同时保证数字不重复消耗。以下是可运行的实现代码:
import itertools import math import operator # 运算符字符串到实际计算函数的映射 op_map = { '+': operator.add, '-': operator.sub } # 函数对象到名称字符串的映射(用于生成表达式文本) func_name_map = { math.log: 'log', math.exp: 'exp' } def generate_expressions(numbers): expressions = [] n = len(numbers) # 基础情况:单个数字的表达式 if n == 1: num = numbers[0] # 纯数字表达式 expressions.append((str(num), num)) # 函数作用于单个数字的表达式(跳过无效计算,比如log(0)) for fn in func_name_map: try: val = fn(num) expr_str = f"{func_name_map[fn]}({num})" expressions.append((expr_str, val)) except ValueError: continue return expressions # 递归拆分数字为两个非空子集,生成组合表达式 for split_idx in range(1, n): # 生成所有可能的数字拆分方式(保证数字不重复使用) for left_nums in itertools.combinations(numbers, split_idx): right_nums = tuple(set(numbers) - set(left_nums)) # 递归生成左右子集的所有子表达式 left_exprs = generate_expressions(left_nums) right_exprs = generate_expressions(right_nums) # 用运算符连接左右子表达式 for (left_str, left_val), (right_str, right_val) in itertools.product(left_exprs, right_exprs): for op_str, op_func in op_map.items(): try: calc_val = op_func(left_val, right_val) # 给复杂子表达式加括号避免歧义 left_part = f"({left_str})" if len(left_nums) > 1 else left_str right_part = f"({right_str})" if len(right_nums) > 1 else right_str expr_str = f"{left_part} {op_str} {right_part}" expressions.append((expr_str, calc_val)) except: continue # 去重:避免不同生成路径产生相同表达式 unique_exprs = [] seen = set() for expr_str, val in expressions: if expr_str not in seen: seen.add(expr_str) unique_exprs.append((expr_str, val)) return unique_exprs # 测试运行 numbers = (9, 0, 1) all_expressions = generate_expressions(numbers) # 打印部分示例结果 print("部分生成的表达式:") for expr, _ in all_expressions[:10]: print(expr) print("...")
代码说明
- 映射表:
op_map和func_name_map分别处理运算符的计算逻辑和函数的文本展示,方便生成可读的表达式字符串。 - 递归逻辑:
- 单个数字时,生成纯数字和函数作用于数字的两种表达式。
- 多个数字时,拆分数字为所有可能的非空子集,递归生成子表达式后用运算符连接,覆盖
a op b、a op func(b)、func(a op b)等所有组合结构。
- 去重处理:避免因拆分顺序不同(如先拆a和b+c,再拆a+b和c)生成重复表达式。
- 异常处理:跳过无效计算(如
log(0)),避免程序崩溃。
扩展方向
- 新增运算符:在
op_map中添加'*': operator.mul、'/': operator.truediv等即可。 - 新增函数:在
func_name_map中添加自定义函数或更多math模块函数(如math.sqrt)。 - 过滤规则:可根据需求添加更多表达式过滤条件(如排除负数结果、限制表达式长度)。
内容的提问来源于stack exchange,提问作者Ravi
相关产品推荐
相关产品推荐

