使用列表推导式解决 Collat​​z 猜想

Jay*_*gov 2 python list-comprehension

有没有一种方法可以使用列表推导式来检验 Collat​​z 猜想,而无需使用 while 语句或其他方法将 n 值附加到 ls 中,而无需在每个语句后添加 ls ?

from random import choice
from time import sleep

n = choice([x for x in range(2, 99*99) if all(x%y != 0 for y in range(2, x))])
ls = []
ls.append(n)
while True:
    if n % 2 == 0:
        n = n // 2
        ls.append(n)
    elif n % 2 != 0:
        n = (3 * n) + 1
        ls.append(n)
    if n == 1:
        break
print(ls)
Run Code Online (Sandbox Code Playgroud)

Kel*_*ndy 6

一种方法(“丢失”初始数字,但我认为这对于目的并不重要):

\n
print(f\'{n}:\')\nprint([n := 3*n+1 if n%2 else n//2\n       for _ in iter(lambda: n, 1)])\n
Run Code Online (Sandbox Code Playgroud)\n

输出n = 92

\n
92:\n[46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]\n
Run Code Online (Sandbox Code Playgroud)\n

一个(ab)使用基于 kolypto 的列表组合:

\n
print([memo\n       for memo in [[n]]\n       for n in memo\n       if n == 1 or memo.append(n//2 if n%2==0 else n*3+1)\n      ][0])\n
Run Code Online (Sandbox Code Playgroud)\n

输出n = 92

\n
[92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]\n
Run Code Online (Sandbox Code Playgroud)\n

我仍然认为while循环是合适的方式,但事实证明它并没有快很多。求解从 1 到 5000 的所有 n 的时间:

\n
 78 ms  while_loop_ewz93\n 87 ms  list_comp_Kelly\n126 ms  list_comp_kolypto\n 82 ms  list_comp_kolypto_Kellied\n
Run Code Online (Sandbox Code Playgroud)\n

我的iter(lambda: n, 1)模拟while n != 1:。更一般地,while condition:可以使用 进行模拟iter(lambda: bool(condition), False)。(例如,bool如果条件已经是 a ,则不需要显式的。)booliter(lambda: mystring.startswith(\'x\'), False)

\n

基准代码(在线尝试!)与 ewz93 和 kolypto 的修改为也不包括起始编号(为了更公平的比较):

\n
from timeit import repeat\n\ndef while_loop_ewz93(n):\n    ls = []\n    while n != 1:\n        n = n // 2 if n % 2 == 0 else (3 * n) + 1\n        ls.append(n)\n    return ls\n\ndef list_comp_Kelly(n):\n    return [n := 3*n+1 if n%2 else n//2\n            for x in iter(lambda: n, 1)]\n\ndef list_comp_kolypto(n):\n    return [\n        *(lambda memo: [\n            memo.append(n // 2 if n%2==0 else n*3+1) or memo[-1]\n            for n in memo\n            if memo[-1] != 1\n        ])([n])\n    ]\n\ndef list_comp_kolypto_Kellied(n):\n    return [\n        memo\n        for memo in [[n]]\n        for n in memo\n        if n == 1 or memo.append(n//2 if n%2==0 else n*3+1)\n    ][0]\n\nfuncs = [\n    while_loop_ewz93,\n    list_comp_Kelly,\n    list_comp_kolypto,\n    list_comp_kolypto_Kellied,\n]\n\nfor _ in range(3):\n    for func in funcs:\n        t = min(repeat(lambda: list(map(func, range(1, 5001))), number=1))\n        print(\'%3d ms \' % (t * 1e3), func.__name__)\n    print()\n
Run Code Online (Sandbox Code Playgroud)\n