You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的Countdown求解器触发Python最大递归深度超限错误?

Countdown求解器递归深度超限问题分析

我正在实现热门电视节目《Countdown》的求解器,功能是给定6个数字和一个目标数字,遍历所有可能的解法直至找到一个并返回。不需要高度优化版本,只需要一个易于集成到更大程序中的简单函数。

运行代码时触发了最大递归深度超限错误,原以为只会执行5次递归调用(从6个数字到2个数字需要5次递归),不清楚错误原因。

求解器预期逻辑:

  • 数字列表以字符串形式传入,循环中用4种运算组合每对数字(注意a + b = b + a),并与目标值比对。
  • 运算结果替换原列表中的两个数字,生成元素数少1的新列表,例如:
    ["7","9","50","25","75","100"] => ["63","50","25","75","100"]
    
  • 用新列表递归调用自身,直到列表只剩2个元素:
    • 未找到解法返回"Q",后续调用也会返回"Q";
    • 找到解法则返回运算字符串,比如"(7 * 9)"。
  • 递归返回时会替换表达式中的中间结果,最终生成完整表达式,比如"(5 + (7 * 9))"。

用户提供的代码:

import itertools as i

target=input("What is the target number? ")

def solve(l):
  global count
  if len(l) == 2:
    count+=1
    if int(l[0]) + int(l[1]) == target:
      return "("+l[0] +" + "+l[1]+")"
    count+=1
    if int(l[0]) - int(l[1]) == target:
      return "("+l[0] +" - "+l[1]+")"
    count+=1
    if int(l[0]) * int(l[1]) == target:
      return "("+l[0] +" * "+l[1]+")"
    count+=1
    if int(l[0]) / int(l[1]) == target:
      return "("+l[0] +" / "+l[1]+")"
    count+=1
    if int(l[1]) - int(l[0]) == target:
      return "("+l[0] +" - "+l[1]+")"
    count+=1
    if int(l[1]) / int(l[0]) == target:
      return "("+l[1] +" / "+l[0]+")"
    else:
      return "Q"
  else:
    ct = list(i.combinations(l, 2))
    for item in ct:
      count+=1
      resulta1=int(item[0])+int(item[1])
      if resulta1 == target:
        return "("+item[0] +" + "+item[1]+")"
      count+=1
      resulta2=int(item[0])-int(item[1])
      if resulta2 == target:
        return "("+item[0] +" - "+item[1]+")"
      count+=1
      resulta3=int(item[0])*int(item[1])
      if resulta3 == target:
        return "("+item[0] +" * "+item[1]+")"
      count+=1
      resulta4=int(item[0])/int(item[1])
      if resulta4 == target:
        return "("+item[0] +" / "+item[1]+")"
      count+=1
      resulta5=int(item[1])-int(item[0])
      if resulta5 == target:
        return "("+item[0] +" - "+item[1]+")"
      count+=1
      resulta6=int(item[1])+int(item[0])
      if resulta6 == target:
        return "("+item[1] +" / "+item[0]+")"
      intl = [el for el in l]
      intl.remove(item[0])
      intl.remove(item[1])
      newl=intl
      newl.append(str(resulta1))
      res1=solve(newl)
      if res1 != "Q":
        return res1.replace(str(resulta1),"("+item[0] +" + "+item[1]+")")
      newl=intl
      newl.append(str(resulta2))
      res2=solve(newl)
      if res2 != "Q":
        return res2.replace(str(resulta2),"("+item[0] +" - "+item[1]+")")
      newl=intl
      newl.append(str(resulta3))
      res3=solve(newl)
      if res3 != "Q":
        return res3.replace(str(resulta3),"("+item[0] +" * "+item[1]+")")
      newl=intl
      newl.append(str(resulta4))
      res4=solve(newl)
      if res4 != "Q":
        return res4.replace(str(resulta4),"("+item[0] +" / "+item[1]+")")
      newl=intl
      newl.append(str(resulta5))
      res5=solve(newl)
      if res5 != "Q":
        return res5.replace(str(resulta5),"("+item[1] +" - "+item[0]+")")
      newl=intl
      newl.append(str(resulta6))
      res6=solve(newl)
      if res6 != "Q":
        return res6.replace(str(resulta6),"("+item[1] +" / "+item[0]+")")
      else:
        return "Q"

lis=input("Enter numbers separated by commas: ").split(",")
count=0
solution = solve(lis)
print(count)

递归超限的核心原因

  1. 列表引用错误导致无限递归
    newl=intl是引用赋值,不是创建新列表,后续修改newl会直接改变intl的内容。比如第一次newl.append(str(resulta1))后,intl也会多出这个元素,后续再用newl=intl创建新列表时,长度会越来越长,永远无法触发len(l)==2的终止条件,导致无限递归。

  2. 目标值类型不匹配
    target是input()获取的字符串,代码中直接和整数运算结果比较(比如int(item[0])+int(item[1]) == target),这会永远不成立,导致所有路径都走到递归分支,进一步加剧递归次数。

  3. 循环内提前返回"Q"
    在for item in ct:循环的最后写了else: return "Q",导致第一次处理完一组数字的所有运算后,不管后续有没有其他组合,直接返回"Q",程序没有机会遍历所有可能的路径,同时错误的递归逻辑会反复触发调用。

修复方案

1. 修正目标值类型

将输入的target转为整数:

target = int(input("What is the target number? "))

2. 修复列表引用问题

创建新列表时使用拷贝,避免引用同一对象:

# 替换所有newl=intl的写法
newl = intl.copy()  # 或 newl = list(intl)

3. 调整循环返回逻辑

将return "Q"移到循环外,只有遍历完所有数字组合都没找到解时才返回:

else:
    ct = list(i.combinations(l, 2))
    for item in ct:
        # ... 原有运算处理逻辑 ...
        # 去掉循环内的else: return "Q"
    # 所有组合遍历完成后再返回Q
    return "Q"

4. 修正运算判断错误

比如resulta6的判断逻辑错误,应该是除法运算而非加法:

resulta6 = int(item[1]) / int(item[0])
if resulta6 == target:
    return "("+item[1] +" / "+item[0]+")"

同时注意除法的浮点数精度问题,建议用绝对值差判断:

if abs(resulta4 - target) < 1e-9:

5. 修正终止分支的表达式错误

比如int(l[1]) - int(l[0])的判断中,返回的表达式应该对应正确的运算顺序:

if int(l[1]) - int(l[0]) == target:
    return "("+l[1] +" - "+l[0]+")"

内容的提问来源于stack exchange,提问作者Shaken not Stirred

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:54:53