Пятиугольная функция Эйлера в питоне

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
Другие вопросы по тегам