有没有一种更符合python的方式来编码这种循环关系re:OEIS A077947

有没有一种更符合python的方式来编码这种循环关系re:OEIS A077947,python,math,recurrence,oeis,Python,Math,Recurrence,Oeis,我正在写一篇关于Jacobsthal序列(A001045)的论文,以及如何将其视为由一些不同的子序列组成。我在A077947上做了一个评论,指出了这一点,并包含了一个python程序。不幸的是,编写的程序还有很多需要改进的地方,所以我当然想转到堆栈,看看这里是否有人知道如何改进代码 代码如下: a=1 b=1 c=2 d=5 e=9 f=18 for x in range(0, 100): print(a, b, c, d, e, f) a = a+(36*64**x) b = b+

我正在写一篇关于Jacobsthal序列(A001045)的论文,以及如何将其视为由一些不同的子序列组成。我在A077947上做了一个评论,指出了这一点,并包含了一个python程序。不幸的是,编写的程序还有很多需要改进的地方,所以我当然想转到堆栈,看看这里是否有人知道如何改进代码

代码如下:

a=1
b=1
c=2
d=5
e=9
f=18
for x in range(0, 100):
  print(a, b, c, d, e, f)
  a = a+(36*64**x)
  b = b+(72*64**x)
  c = c+(144*64**x)
  d = d+(288*64**x)
  e = e+(576*64**x)
  f = f+(1152*64**x) 
我将其背后的原因解释如下:

a=1
b=1
c=2
d=5
e=9
f=18
for x in range(0, 100):
  print(a, b, c, d, e, f)
  a = a+(36*64**x)
  b = b+(72*64**x)
  c = c+(144*64**x)
  d = d+(288*64**x)
  e = e+(576*64**x)
  f = f+(1152*64**x) 
序列A077947由6个数字保根序列生成 缝合在一起;根据Python代码,这些序列在 种子值a-f。计算给定值所需的迭代次数 A077947 a(n)为~n/6。执行时,代码将返回 A077947达到范围(x),或A077947的~x*6项。我发现这是重复的 当我寻找周期性的数字根保存时,数字根很有趣 作为识别数据中模式的一种方法。对于 例如,数字保根序列使时间序列分析成为可能 估计大型IT中警报的真或假状态时使用大型数据集 进行维护的生态系统(mod7环境);这种分析是错误的 还与预测消费者需求/行为模式相关。 利用这些分析方法,将A077947雕刻成6个数字 保留根序列旨在降低复杂性;Python代码 使用种子值a-f跨6个“通道”复制A077947。这么长 这一段话可以归结为一句话,“数字根的术语” 序列在模式(1,1,2,5,9,9)中重复 所有数字根重复一个模式的序列都可以 被分割/分离成相同数量的不同序列 序列可以独立计算。有一笔赏金是关于 这个序列

这个代码很难看,但如果不这样编码,我似乎无法得到正确的答案

我还没有弄明白如何将其作为函数来编写,因为我似乎无法在函数中正确存储递归值

因此,当然,如果这产生了良好的结果,我们希望将讨论与OEIS参考联系起来

这里是序列的链接:

这与您的代码的行为相同,可以说更漂亮。您可能会看到一些方法来减少魔法常数的随意性

factors = [ 1, 1, 2, 5, 9, 18 ]
cofactors = [ 36*(2**n) for n in range(6) ]

for x in range(10):
    print(*factors)
    for i in range(6):
        factors[i] = factors[i] + cofactors[i] * 64**x

只计算其中一个子序列,在迭代时将
i
保持固定就足够了。

这将与您的代码表现相同,并且可以说更漂亮。您可能会看到一些方法来减少魔法常数的随意性

factors = [ 1, 1, 2, 5, 9, 18 ]
cofactors = [ 36*(2**n) for n in range(6) ]

for x in range(10):
    print(*factors)
    for i in range(6):
        factors[i] = factors[i] + cofactors[i] * 64**x

要只计算其中一个子序列,在迭代时保持
i
固定就足够了。

这里有一种不需要第二个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模3-1(假设指数为零)

因此,生成序列的简单循环可以是:

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])
但您也可以使用基于通道索引(和通道数)的更通用公式:

或(基于2*S+i%3-1的6个通道):

我在这里的推理是,如果有一个函数可以根据当前索引和序列中的值计算下一个值,那么应该能够定义一个跨步函数,该函数将计算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

请注意,从第三个值开始,可以在不知道索引的情况下计算该序列中的下一个值:


A001045:F(S)=2*S+1-2*0**((S+1)%4)

这里有一种不使用第二个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模3-1(假设指数为零)

因此,生成序列的简单循环可以是:

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)