Я не понимаю алгоритм и понятия не имею, является ли мое предлагаемое изменение алгоритма (ниже) правильным или нет. Все, что я знаю, это то, что он выдает ожидаемый результат, который вы цитируете для n = 4:
def generate_oriented_forest(n):
"""Algorithm O from Knuth TAoCP, Fascicle 4, p. 25. """
p = range(-1,n)
while True:
yield p[1:]
if p[n] > 0:
p[n] = p[p[n]]
continue
for k in range(n-1,0,-1):
if p[k] != 0: break
else:
break
j = p[k]
d = k-j
while True:
if p[k-d] == p[j]:
p[k] = p[j]
else:
p[k] = p[k-d]
if k==n:
break
k+=1
Я использовал код Гнибблера в качестве отправной точки. Я использовал traceit () и операторы печати, чтобы следовать коду при его переходе от [0, 1, 1, 0] -> [0, 1, 0, 3].
Я обнаружил, что это состояние переменных:
[0, 1, 1, 0] # the last yield
k: 4
d: 2
j: 1
p: [-1, 0, 1, 0, 0]
[0, 1, 0, 3] # the problem yield
и это единственный раз, когда выполняется этот код:
__main__:19: if p[k-d] == p[j]:
__main__:22: p[k] = p[k-d] + d
Поскольку p [k-d] = p [2] = 1, и вы хотите, чтобы p [k] равнялось 1, я «думаю», правильная формула должна быть
р [к] = р [к-d].
Я тоже изменился
for k in range(n-1,-1,-1):
до
for k in range(n-1,0,-1):
чтобы код не выдал дополнительный [0, 0, 0, 0] в конце.