Фибоначчиевые кролики умирают после произвольных # месяцев

Итак, я видел несколько решений для этой проблемы или подобных проблем, но я действительно хочу знать, почему мой не работает. Это намного легче читать, чем множество решений, которые я нашел, поэтому я хотел бы заставить его работать!

Начиная с 1 пары кроликов, которые начнут воспроизводиться через 2 месяца. Бегите в течение n месяцев, когда кролики умирают после того, как они прожили в течение месяцев. Ввод "6 3" должен возвращать 4, но он возвращает 3.

#run for n months, rabbits die after m months.
n, m = input("Enter months to run, and how many months rabbits live, separated by a space ").split() 
n, m = int(n), int(m)
generations = [1, 1, 2] #Seed the sequence with the 1 pair, then in their reproductive month.
def fib(i, j):
    count = 3 #we start at the 3rd generation.
    while (count < i):
        if (count < j):
            generations.append(generations[count-2] + generations[count-1]) #recurrence relation before rabbits start dying
        else:                                                               #is just the fib seq (Fn = Fn-2 + Fn-1)
            generations.append((generations[count-2] + generations[count-1]) - generations[(count-j)])  #Our recurrence relation when rabbits die every month
        count += 1                                                          #is (Fn = Fn-2 + Fn-1 - Fn-j)
    return (generations[count-1])


print (fib(n, m))
print ("Here how the total population looks by generation: \n" + str(generations))

Спасибо =]

Ответ 1

Это копируется из ответа в вопросе SpaceCadets, чтобы помочь выполнить его из "неотвеченного" списка вопросов.


Два ключа здесь составляли дерево на большое количество, и, конечно же, включали проверку базового регистра для первого и второго поколений смертей (это -1 в обоих случаях, а затем это то, что зависит от ввода).

Итак, 3 возможных случая. Регулярная последовательность фишек, когда нам не нужно учитывать смертность, первое и второе поколение смертей для инициализации нашей конечной последовательности с рекуррентным соотношением Fn-2 + Fn-1 - Fn- (monthsAlive + 1)

Я уверен, что есть способ объединить 1 или 2 из этих проверок и сделать алгоритм более эффективным, но на данный момент он сразу и правильно решил большой тестовый пример (90, 17). Поэтому я счастлив.

Извлеченный урок: используйте всю белую доску.

#run for n months, rabbits die after m months.
n, m = input("Enter months to run, and how many months rabbits live, separated by a space ").split() 
n, m = int(n), int(m)
generations = [1, 1] #Seed the sequence with the 1 pair, then in their reproductive month.
def fib(i, j):
    count = 2
    while (count < i):
        if (count < j):
            generations.append(generations[-2] + generations[-1]) #recurrence relation before rabbits start dying (simply fib seq Fn = Fn-2 + Fn-1)
        elif (count == j or count == j+1):
            print ("in base cases for newborns (1st+2nd gen. deaths)") #Base cases for subtracting rabbit deaths (1 death in first 2 death gens)
            generations.append((generations[-2] + generations[-1]) - 1)#Fn = Fn-2 + Fn-1 - 1
        else:
            generations.append((generations[-2] + generations[-1]) - (generations[-(j+1)])) #Our recurrence relation here is Fn-2 + Fn-1 - Fn-(j+1)
        count += 1
    return (generations[-1])


print (fib(n, m))
print ("Here how the total population looks by generation: \n" + str(generations))

Ответ 2

Здесь есть два случая для отношения повторения. Учитывая, что n - количество месяцев, в течение которых выполняется последовательность, а m - количество месяцев, в течение которых пара будет жить:

1) Если индекс в последовательности (на основе нуля) меньше m:
Обычный Фибоначчи (Текущий термин = предыдущий термин + тот, который перед ним).

2) Если индекс больше или равен m:
Текущий термин = сумма (m - 1) предыдущих терминов (игнорируя тот, который был непосредственно до этого).

Вот пример с последовательностью с именем A и m = 5:
A5 = A0 + A1 + A2 + A3 (4 члена, т.е. m - 1, игнорируя тот, который был непосредственно перед этим)
  .
Если m = 3, то:
A3 = A0 + A1 (всего 2 члена, m - 1)

.

Код ниже (в Python) имеет смещение на 2 из-за начального [1, 1] в начале последовательности.

def mortal_rabbits(n, m):
    sequence = [1, 1]

    for i in range(n - 2):
        new_num = 0
        if i + 2 < m:
            #Normal fibonacci - No deaths yet
            new_num = sequence[i] + sequence[i + 1]
        else:
            #Different reoccurence relation - Accounting for death
            for j in range(m - 1):
                new_num += sequence[i - j]

        sequence.append(new_num)

    return sequence

Ответ 3

Игнорируя сложности, уравнение для количества пар кроликов в генерации

rabbit_pairs

Если мы используем список, это представляет проблему, потому что, когда n == m, нам нужно значение, которое находится в позиции -1, что явно выходит за пределы.

def rabbit_pairs(n, m):
    sequence = list()
    for i in range(n):
        if i < 2:
            # Normal Fibonacci initialization
            total = 1
            sequence.append(total)
        elif (i < m) or (m == 0):
            # Normal Fibonacci calculation
            total = sequence[i - 1] + sequence[i - 2]
            sequence.append(total)
        elif i == m:
            # Now we need R(n - (m + 1)), but i - (m + 1) < 0, so we have to
            # provide the missing value
            total = sequence[i - 1] + sequence[i - 2] - 1
            sequence.append(total)
        else:
            # i - (m + 1) >= 0, so we can get the value from the sequence
            total = sequence[i - 1] + sequence[i - 2] - sequence[i - (m + 1)]
            sequence.append(total)
    return total

Ответ 4

Использование рекурсии.

public static int fibRec(int months, int dieAfter) {
    if(months <= 0) return 0;
    if(months == 1) return 1;
    if(months <= dieAfter)
        return fibRec(months-1, dieAfter) + fibRec(months-2, dieAfter);
    else if (months == dieAfter+1)
        return fibRec(months-1, dieAfter) + fibRec(months-2, dieAfter) - 1;
    else
        return fibRec(months-1, dieAfter) + fibRec(months-2, dieAfter) 
                 - fibRec(months-(dieAfter+1), dieAfter);
}