我一直在试图“进一步”改变我的内心,并偶然发现了这一点。如果我不禁止使用多行,只需使用一段时间即可。
所以我试图解决的示例问题如下(在其中一个编码站点上找到它:codercharts,codeeval等):
问题如下:选择一个数字,反转其数字并将其添加到原始数字。如果总和不是回文(这意味着它从左到右,从右到左不是相同的数字),重复此过程。
超级简单吧?一段时间就足够了,但我真的不知道如何在满足某个条件之前生成数字。我已经检查了itertools.takeWhile
和itertools.dropWhile
,但这些都与现有列表一起使用,我仍然需要生成这些列表。
我尝试了生成器,但是我不知道如何在一行中压缩它们。
Argh,在Haskell中创建一个无限列表然后使用takeWhile会起作用,但在Python中我被卡住了。任何指向正确方向的指针都将非常感激。
编辑: 为了更简洁,我试图在一行上做这件事(当然是减去进口)。
答案 0 :(得分:4)
我首先以递归的方式写这个:
def frob(x):
if str(x) == str(x)[::-1]:
return x
else:
return frob(x + int(str(x)[::-1]))
print frob(29)
然后,由于lambda不能通过名称引用自身,我将删除显式递归并要求用户将该函数作为参数传递给自身。
def frob(f, x):
if str(x) == str(x)[::-1]:
return x
else:
return f(f, x + int(str(x)[::-1]))
print frob(frob, 29)
这允许您将frob
写为一行。
def frob(f, x):
return x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1]))
print frob(frob, 29)
然后可以将其变成lambda函数。
frob = lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1]))
print frob(frob, 29)
您可以使用fixed point combinator修改函数的签名,以便它不再需要您明确地传递自己。
frob = (lambda f: lambda x: f(f,x))(lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1])))
print frob(29)
此时,您根本不再需要分配,并且可以在一行中调用lambda。
print (lambda f: lambda x: f(f,x))(lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1])))(29)
编辑:我刚刚注意到我误读了原来的问题陈述 - 有必要将该号码至少添加一次,即使它最初是一个回文。在这种情况下,我们仍然可以使用相同的函数,但是我们必须将它包装在执行第一步的内容中。
def troz(x):
return frob(x + int(str(x)[::-1]))
减少到:
print (lambda x: (lambda f: lambda x: f(f,x))(lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1])))(x + int(str(x)[::-1])))(29)