Пятиугольная функция Эйлера в питоне
max = 200
max=max+2 ### due to the later code, it got offset by 2
P = [0]*max ### make a list of zeros, length max
P[0] = 1
P[1] = 1
print 0,":", P[0] ### print value for n = 0,1
print 1,":", P[1]
Psign = [0]*max ### make a list the same length as P, to store the signs
### apply Euler's pentagonal numbers formula
k = 1
index= k*(3*k-1)/2
while index <=max:
Psign[index] = (-1)**k
index = k*(3*k+1)/2
if index<=max:
Psign[index] = (-1)**k
k=k+1
index = k*(3*k-1)/2
for n in range(1,max+1):
n=n+1
P[n] = 0
for i in range(0,n+1):
i=i+1
P[n] = P[n] - P[n-i]*Psign[i]
print n,":",P[n]
Итак, у меня есть этот код, который может дать ответ на количество разделов n (до 200 в данный момент). Однако, так как я адаптировал код отсюда, который был написан на Mathematica. Я не совсем уверен насчет поздней части. Каким-то образом эта часть портится с моим пределом. Поэтому, если я хочу создать число разделов для 25, я должен установить для моей переменной max значение 27.
Я действительно надеюсь, что кто-то может помочь мне исправить это
Ура,
Alex
1 ответ
Индексирование списка в Python основано на 0, например, список длины n
может быть проиндексирован целыми числами от 0 до n-1
включительно. Не может быть проиндексировано n
, Итак, начните здесь:
P = [0]*max ### make a list of zeros, length max
Вы хотите сослаться на P[max]
позже, но список слишком короткий (на 1) для этого. Так что измените на:
P = [0] * (max + 1)
Вам также необходимо аналогичным образом изменить:
Psign = [0]*max ### make a list the same length as P, to store the signs
чтобы:
Psign = [0] * (max + 1)
Следующий взгляд на:
for n in range(1,max+1):
n=n+1
Это странно - итерация непосредственно по значениям, которые вы хотите. Как заменить эти строки:
for n in range(2, max + 1):
Та же самая странная вещь повторяется затем:
for i in range(0,n+1):
i=i+1
Снова, замените это, чтобы перебрать непосредственно по i
значения, которые вы хотите:
for i in range(n+1):
Наконец, избавьтесь от:
max=max+2 ### due to the later code, it got offset by 2
на вершине. Это просто скрывало некоторые (не все) последствия того, что ваши списки слишком малы для начала.
После внесения всех этих изменений программа работает для меня нормально, и обычно заканчивается финальным выводом:
200 : 3972999029388
Таким образом, вы получили все сложные детали правильно! Вы просто испортили легкие части - LOL;-) Хорошая работа.
Другая функция
Просто для интереса, я включу функцию, которую я использую для этого. Хотя это выглядит совсем по-другому, это действительно один и тот же метод, "оптимизированный" различными способами. Наслаждаться:-)
def p4(n, _p=[1]):
"Number of partitions of n."
from math import sqrt
def inner(n, _p=_p):
k = int((sqrt(24*n+1)-1.) / 6.) + 1
negative = not (k & 1)
i = n - (k*(3*k+1) >> 1)
assert i < 0
s = 0
if i + k >= 0:
s = _p[i+k]
if negative:
s = -s
assert i + 3*k - 1 >= 0
for k in xrange(k-1, 0, -1):
i += 3*k + 2
negative = not negative
t = _p[i] + _p[i + k]
if negative:
t = -t
s += t
assert i+k == n-1
_p[n] = s
if n < 0:
raise ValueError("argument must be >= 0")
oldlen = len(_p)
if n >= oldlen:
_p.extend([None] * (n - oldlen + 1))
for nn in xrange(oldlen, n+1):
inner(nn)
return _p[n]
Тогда, например,
>>> p4(200)
3972999029388L