【问题标题】:Python For Loop includes the end of the rangePython For 循环包括范围的结尾
【发布时间】:2014-03-11 16:28:39
【问题描述】:

我在 checkio.org 上试图解决这个问题:

给你一个两位或多位数字 N。对于这个任务,你应该找到 X 的最小正数,使其数字的乘积等于 N。如果 X 不存在,则返回 0。 让我们来看看这个例子。 N = 20。我们可以将这个数字分解为 2*10,但 10 不是数字。我们也可以将其分解为 4*5 或 2*2*5。 2*2*5 的最小数字是 225,对于 4*5 -- 45。所以我们选择 45。

我创建了对整数进行因式分解的递归函数,并且我将 factoredList 传递给另一个名为“groupIt”的递归函数,以查找作为因式分解整数乘积的最小整数。

函数如下:

def groupIt(digits):
    tempList = []
    if len(digits)>1:
        for z in range(0,len(digits)-1):
            if digits[z]*digits[z+1]>=10:
                toStore=""
                for k in range(0,len(digits)):
                    toStore+=str(digits[k])
                return int(toStore)
            else:
                digits.append(digits.pop(z+1)*digits.pop(z))
                digits.sort()
                tempList.append(groupIt(digits))
    else:
        return digits[0]
    tempList.sort()
    return tempList[0]

对于整数 '20',分解后的列表是 2 x 2 x 5。当我在 [4,5] 上递归调用 groupIt 时,“len(digits)-1” = 1,所以 z 从范围 (0 ,1)。

据我了解,z 应该仅为 0,因为它不包括范围内的最后一个整数,但 z 在 [4,5] 的同一个 for 循环中最终会变为 1。

如果我将“for z in range(0,len(digits)-1)”替换为“for z in range(0,1)”,则代码有效,因此问题似乎在那里孤立。

想法?

【问题讨论】:

  • 请考虑使用首选的for digit in digits: 而不是for z in range(0, len(digits)-1):
  • 如果我只想迭代 len(digits)-1 次,这可行吗?
  • 当我尝试使用groupIt('20') 运行您的代码时,我得到了TypeError: can't multiply sequence by non-int of type 'str'if digits[z]*digits[z+1]>=10: 行。
  • for digit in digits[:-1]
  • 啊,你需要用 groupIt([2,2,5]) 运行它。我有一个单独的、未包含的函数,可将“20”分解为 [2,2,5]。

标签: python range


【解决方案1】:

您的问题是您在尝试迭代 digits 以传递给递归调用时正在改变它(使用 .pop) - 错误不在递归调用中,而是当您返回到外部打电话并尝试移动到下一个z。您应该制作一个副本的数字(例如,使用digits[:])并改变它:

else:
    digits_mod = digits[:]
    digits_mod.append(digits_mod.pop(z+1) * digits_mod.pop(z))
    digits_mod.sort()
    tempList.append(groupIt(digits_mod))

但是,此修改仍然不允许代码适用于例如groupIt([2, 2, 3, 5]),返回 2235 而不是 256

相反。我建议在顶层制作一个列表并将其向下传递,允许在各个级别对其进行修改:

def groupIt(digits, output=None):
    if output is None:
        output = []
    if len(digits)>1:
        for z in range(0,len(digits)-1):
            if digits[z]*digits[z+1]>=10:
                toStore=""
                for k in range(0,len(digits)):
                    toStore+=str(digits[k])
                output.append(int(toStore)) # note storage here
            else:
                digits_mod = digits[:]
                digits_mod.append(digits_mod.pop(z+1) * digits_mod.pop(z))
                digits_mod.sort()
                groupIt(digits_mod, output) # note call here
    else:
        return digits[0] # still need this for single digit case
    return min(output)

现在递归调用忽略return 值,允许将最终的完整output 的最小值返回到首先调用的groupIt

我得到,例如:

>>> groupIt([2, 2, 3, 5])
256

(返回前output == [345, 345, 256, 256, 2235])。


相同逻辑的更简洁版本:

def groupIt(lst, out=None):
    if out is None:
        out = set()
    out.add(int("".join(map(str, sorted(lst)))))
    if len(lst) > 1:
        for i in range(len(lst)-1):
            n = lst[i] * lst[i+1]
            if n < 10:
                groups(lst[:i] + [n] + lst[i+2:], out)
    return min(out)

【讨论】:

  • 啊,我必须小心我变异的东西。谢谢!
  • 没问题。我刚刚添加了相同逻辑的更简洁版本。
猜你喜欢
  • 1970-01-01
  • 2012-08-25
  • 2022-12-16
  • 1970-01-01
  • 2018-12-20
  • 2023-03-18
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多