这是一种无需第二个 for 循环的替代方法:
sequences = [ 1, 1, 2, 5, 9, 18 ]
multipliers = [ 36, 72, 144, 288, 576, 1152 ]
for x in range(100):
print(*sequences)
sequences = [ s + m*64**x for s,m in zip(sequences,multipliers) ]
[编辑] 查看我注意到这个特定序列的值也可以通过以下方式获得:
N[i+1] = 2 * N[i] + (-1,0,1 旋转)
或者
N[i+1] = 2 * N[i] + i mod 3 - 1 (假设从零开始的索引)
i N[i] [-1,0,1] N[i+1]
0 1 -1 --> 2*1 - 1 --> 1
1 1 0 --> 2*1 + 0 --> 2
2 2 1 --> 2*2 + 1 --> 5
3 5 -1 --> 2*5 - 1 --> 9
4 9 0 --> 2*9 + 0 --> 18
...
因此,产生序列的更简单的循环可能是:
n = 1
for i in range(100):
print(n)
n = 2*n + i % 3 - 1
使用 functools 中的 reduce 函数可以使这更加简洁:
from functools import reduce
sequence = reduce(lambda s,i: s + [s[-1]*2 + i%3 - 1],range(20),[1])
print(sequence)
>>> [1, 1, 2, 5, 9, 18, 37, 73, 146, 293, 585, 1170, 2341, 4681, 9362, 18725, 37449, 74898, 149797, 299593, 599186]
使用您的多渠道方法和我建议的公式,这将给出:
sequences = [ 1, 1, 2, 5, 9, 18 ]
multipliers = [ 36, 72, 144, 288, 576, 1152 ]
allSequences = reduce(lambda ss,x: ss + [[ s + m*64**x for s,m in zip(ss[-1],multipliers) ]],range(100),[sequences])
for seq in allSequences: print(*seq) # print 6 by 6
[EDIT2] 如果您的所有序列都将具有相似的模式(即起始通道、乘数和计算公式),您可以在函数中推广此类序列的打印,因此每个序列只需要一行:
def printSeq(calcNext,sequence,multipliers,count):
for x in range(count):
print(*sequence)
sequence = [ calcNext(x,s,m) for s,m in zip(sequence,multipliers) ]
printSeq(lambda x,s,m:s*2+m*64**x,[1,1,2,5,9,18],multipliers=[36,72,144,288,576,1152],count=100)
[EDIT3] 改进 printSeq 函数。
我相信您并不总是需要一个乘数数组来计算每个通道中的下一个值。该函数的改进是为 lambda 函数提供通道索引而不是乘数。如果需要,这将允许您使用乘数数组,但也可以让您使用更通用的计算。
def printSeq(name,count,calcNext,sequence):
p = len(sequence)
for x in range(count):
print(name, x,":","\t".join(str(s) for s in sequence))
sequence = [ calcNext(x,s,c,p) for c,s in enumerate(sequence) ]
lambda 函数有 4 个参数,预计会返回指定通道的下一个序列值:
s : current sequence value for the channel
x : iteration number
c : channel index (zero based)
p : number of channels
因此,在公式中使用数组将表示如下:
printSeq("A077947",100,lambda x,s,c,p: s + [36,72,144,288,576,1152][c] * 64**x, [1,1,2,5,9,18])
但是您也可以使用基于通道索引(和通道数)的更通用的公式:
printSeq("A077947",100,lambda x,s,c,p: s + 9 * 2**(p*x+c+2), [1,1,2,5,9,18])
或(基于 2*S + i%3 - 1 的 6 个通道):
printSeq("A077947",100,lambda x,s,c,p: 64*s + 9*(c%3*2 - (c+2)%3 - 1) ,[1,1,2,5,9,18])
printSeq("A077947",100,lambda x,s,c,p: 64*s + 9*[-3,1,2][c%3],[1,1,2,5,9,18])
我的理由是,如果您有一个可以根据当前索引和序列中的值计算下一个值的函数,您应该能够定义一个跨步函数,该函数将计算 N 个索引更远的值。
给定 F(i,S[i]) --> i+1,S[i+1]
F2(i,S[i]) --> i+2,S[i+2] = F(F(i,S[i]))
F3(i,S[i]) --> i+3,S[i+3] = F(F(F(i,S[i])))
...
F6(i,S[i]) --> i+6,S[i+6] = F(F(F(F(F(F(i,S[i]))))))
...
Fn(i,S[i]) --> i+n,S[i+n] = ...
这将始终有效,并且不需要乘法器数组。大多数时候,应该可以仅使用代数来简化 Fn。
例如 A001045 : F(i,S) = i+1, 2*S + (-1)**i
printSeq("A001045",20,lambda x,s,c,p: 64*s + 21*(-1)**(x*p+c),[0,1,1,3,5,11])
请注意,从第 3 个值开始,可以在不知道索引的情况下计算该序列中的下一个值:
A001045: F(S) = 2*S + 1 - 2*0**((S+1)%4)