Python中的递归用于日常编码挑战
我试图解决一些我在网上发现的编码难题。然而,我被下面的问题阻止了。我试图用递归来解决这个问题,但我觉得我缺少了递归中一个非常重要的概念。我的代码适用于以下所有示例,但最后一个示例除外 有人能指出我在递归代码中犯的错误吗?或者指导我解决这个问题 我知道为什么我的代码会中断,但我不知道如何绕过Python中的“通过对象引用传递”,我认为这会给我带来更大的问题 编码问题是: 在一个神秘的岛屿上,有一种叫做古克斯的生物,有三种颜色:红色、绿色和蓝色。Qux的一种力量是,如果它们中的两个站在一起,它们可以变成一个单一的第三种颜色的生物 假设N个qux排成一行,确定在任何可能的转换序列之后剩余的最小qux数。 例如,给定输入Python中的递归用于日常编码挑战,python,recursion,Python,Recursion,我试图解决一些我在网上发现的编码难题。然而,我被下面的问题阻止了。我试图用递归来解决这个问题,但我觉得我缺少了递归中一个非常重要的概念。我的代码适用于以下所有示例,但最后一个示例除外 有人能指出我在递归代码中犯的错误吗?或者指导我解决这个问题 我知道为什么我的代码会中断,但我不知道如何绕过Python中的“通过对象引用传递”,我认为这会给我带来更大的问题 编码问题是: 在一个神秘的岛屿上,有一种叫做古克斯的生物,有三种颜色:红色、绿色和蓝色。Qux的一种力量是,如果它们中的两个站在一起,它们可以
['R','G','B','G','B']
,可以通过以下步骤以单个Qux结束:
Arrangement | Change
----------------------------------------
['R', 'G', 'B', 'G', 'B'] | (R, G) -> B
['B', 'B', 'G', 'B'] | (B, G) -> R
['B', 'R', 'B'] | (R, B) -> G
['B', 'G'] | (B, G) -> R
['R'] |
________________________________________
我的代码是:
class fusionCreatures(object):
"""Regular Numbers Gen.
"""
def __init__(self , value=[]):
self.value = value
self.ans = len(self.value)
def fusion(self, fus_arr, i):
color = ['R','G','B']
color.remove(fus_arr[i])
color.remove(fus_arr[i+1])
fus_arr.pop(i)
fus_arr.pop(i)
fus_arr.insert(i, color[0])
return fus_arr
def fusionCreatures1(self, arr=None):
# this method is to find the smallest number of creature in a row after fusion
if arr == None:
arr = self.value
for i in range (0,len(arr)-1):
#print(arr)
if len(arr) == 2 and i >= 1 or len(arr)<2:
break
if arr[i] != arr[i+ 1]:
arr1 = self.fusion(arr, i)
testlen = self.fusionCreatures1(arr)
if len(arr) < self.ans:
self.ans = len(arr)
return self.ans
我首先要提到的是,有一种演绎方法在O(n)中有效,并在本文中详细介绍。它归结为检查列表中三种类型元素的计数的奇偶性,以确定几个固定结果中的哪一个发生 您提到您更喜欢使用递归方法,即O(n!)。这是一个很好的开始,因为它可以作为一个工具来帮助获得O(n)解决方案,并且是一种常见的递归模式 因为我们不知道两个qux之间的给定融合是否最终会导致一个最优的全局解决方案,所以我们不得不尝试各种可能性。我们通过浏览列表并寻找潜在的融合来实现这一点。当我们找到一个时,在一个新列表中执行转换,并在其上调用
fuse\u qxes
。在这一过程中,我们将跟踪所达到的最小长度
这里有一种方法:
def fuse_quxes(quxes, choices="RGB"):
fusion = {x[:-1]: [x[-1]] for x in permutations(choices)}
def walk(quxes):
best = len(quxes)
for i in range(1, len(quxes)):
if quxes[i-1] != quxes[i]:
sub = quxes[:i-1] + fusion[quxes[i-1], quxes[i]] + quxes[i+1:]
best = min(walk(sub), best)
return best
return walk(quxes)
这几乎是您提供的代码的发展方向,但实现似乎不清楚。不幸的是,我没有看到任何单一或快速的解决办法。以下是一些一般性问题:
- 将
函数放入一个类中,允许它改变外部状态,即fusioncreates1
和self.value
self.ans
的名称特别糟糕,难以跟踪。其目的似乎是将其用作参考副本,以将self.value
重置为其默认值,但arr
意味着当arr=self.value
在fus\u arr
中发生变异时,fusion()
也会发生变化。所有内容几乎都是对一个基本列表的引用 向这些副本添加切片至少可以使程序更容易推理,例如,self.value
函数中的fusion()
和arr=self.value[:]
。简而言之,试着去写fus\u arr=fus\u arr[:]
也不清楚,不必要;最好将结果值降级为递归函数中的局部变量 似乎没有必要将无状态函数放入类中,除非它是纯静态方法,并且该类充当名称空间self.ans
- 认知过载的另一个原因是分支语句,如
和if
。我们希望尽量减少这些的频率和嵌套。以下是伪代码中的break
,带有突变和复杂相互作用的注释:fusioncreates1
您可能会同意,在运行此函数时,很难在心理上逐步完成def fusionCreatures1(): if ... read mutated global state for i in len(arr): if complex length and index checks: break if arr[i] != arr[i+ 1]: impure_func_that_changes_arr_length(arr) recurse() if new best compared to global state: mutate global state
- 在
中,有两个变量未使用:fusionCreatures1()
赋值arr1 = self.fusion(arr, i) testlen = self.fusionCreatures1(arr)
(连同arr1=self.fusion(arr,i)
)似乎表明人们不了解返回fus\u arr
实际上是一个变异参数数组的函数。所以调用它意味着self.fusion
,我们还有另一个别名变量需要解释 除此之外,程序中既没有使用arr1是arr
也没有使用arr1
,因此意图不明确 一个好的工具会发现这些未使用的变量,并识别我提到的大多数其他复杂性问题testlen
- 在循环列表时对其进行变异通常是灾难性的
在一个循环内变异self.fusion(arr,i)
,这使得很难对其长度进行推理,并且当arr
不再匹配函数体中的实际范围(len(arr))
时,会导致索引错误(或者至少需要一个体内先决条件)。如上所述,使用切片将len(arr)
变得纯粹,可以修复此问题,但揭示了不存在递归,从而导致堆栈溢出错误self.fusion(arr,i)
- 避免使用变量名,如
,arr
,arr1
,除非上下文明显。同样,这些混淆了意图,使程序难以理解value
- 根据使用
。类名应snake\u案例
,以区别于函数。不需要从标题化
——这是隐式的对象继承
- 在函数和运算符周围使用一致的间距:
更清晰,例如range(0,len(arr)-1):
。在块周围使用垂直空格range(len(arr)-1):
- 使用列表,而不是键入
,t1
<代码>t7t2
- 函数名应该是动词,而不是名词。类似于
的类以及名为fusioncreates
的方法尚不清楚。类似于fusioncreates1
make tQuxesSolver.minimize(生物)
arr1 = self.fusion(arr, i) testlen = self.fusionCreatures1(arr)
from collections import defaultdict from itertools import permutations from random import choice, randint def fuse_quxes_linear(quxes, choices="RGB"): counts = defaultdict(int) for e in quxes: counts[e] += 1 if not quxes or any(x == len(quxes) for x in counts.values()): return len(quxes) elif len(set(counts[x] % 2 for x in choices)) == 1: return 2 return 1 def fuse_quxes(quxes, choices="RGB"): fusion = {x[:-1]: [x[-1]] for x in permutations(choices)} def walk(quxes): best = len(quxes) for i in range(1, len(quxes)): if quxes[i-1] != quxes[i]: sub = quxes[:i-1] + fusion[quxes[i-1], quxes[i]] + quxes[i+1:] best = min(walk(sub), best) return best return walk(quxes) if __name__ == "__main__": tests = [ ['R','G','B','G','B'], ['R','G','B','R','G','B'], ['R','R','G','B','G','B'], ['G','R','B','R','G'], ['G','R','B','R','G','R','G'], ['R','R','R','R','R'], ['R', 'R', 'R', 'G', 'G', 'G', 'B', 'B', 'B'] ] for test in tests: print(test, "=>", fuse_quxes(test)) assert fuse_quxes_linear(test) == fuse_quxes(test) for i in range(100): test = [choice("RGB") for x in range(randint(0, 10))] assert fuse_quxes_linear(test) == fuse_quxes(test)
def fuse_quxes(l): n = len(l) for i in range(n - 1): if l[i] == l[i + 1]: continue else: newn = fuse_quxes(l[:i] + [3 - l[i] - l[i + 1]] + l[i+2:]) if newn < n: n = newn return n
IN[5]: fuse_quxes([0, 0, 0, 1, 1, 1, 2, 2, 2]) Out[5]: 2
['R', 'G', 'B', 'G', 'B'] ['R', 'R', 'G', 'B'] ['R', 'B', 'B'] ['G', 'B'] ['R'] Result 1 _______________________ ['R', 'G', 'B', 'R', 'G', 'B'] ['R', 'G', 'B', 'R', 'R'] ['R', 'G', 'G', 'R'] ['B', 'G', 'R'] ['B', 'B'] Result 2 _______________________ ['R', 'R', 'G', 'B', 'G', 'B'] ['R', 'B', 'B', 'G', 'B'] ['G', 'B', 'G', 'B'] ['R', 'G', 'B'] ['R', 'R'] Result 2 _______________________ ['G', 'R', 'B', 'R', 'G'] ['G', 'G', 'R', 'G'] ['G', 'B', 'G'] ['R', 'G'] ['B'] Result 1 _______________________ ['G', 'R', 'B', 'R', 'G', 'R', 'G'] ['G', 'G', 'R', 'G', 'R', 'G'] ['G', 'B', 'G', 'R', 'G'] ['R', 'G', 'R', 'G'] ['B', 'R', 'G'] ['B', 'B'] Result 2 _______________________ ['R', 'R', 'R', 'R', 'R'] Result 5 _______________________ ['R', 'R', 'R', 'G', 'G', 'G', 'B', 'B', 'B'] ['R', 'R', 'B', 'G', 'G', 'B', 'B', 'B'] ['R', 'G', 'G', 'G', 'B', 'B', 'B'] ['B', 'G', 'G', 'B', 'B', 'B'] ['R', 'G', 'B', 'B', 'B'] ['R', 'R', 'B', 'B'] ['R', 'G', 'B'] ['R', 'R'] Result 2 _______________________ [1, 2, 2, 1, 2, 5, 2]