Проект Эйлера #2
Чётные числа Фибоначчи.
Каждый новый член последовательности Фибоначчи получается из суммы двух предыдущих. Начиная с 1 и 2, первые 10 членов последовательности будут:
Найти сумму всех чётных членов последовательности, значения которых не превышают четыре миллиона.
Brute-force решение#
Для начала отбросим тонкости и попробуем решить задачу максимально просто. Так как нам нужно сумму членов последовательности, удовлетворяющих некоторому условию, то необходимо сгенерировать саму последовательность.
Пример реализации на Python#
В реализации решения с помощью Python, воспользуемся генератором. Для этого определим функцию-генератор fibonacci_sequence
, единственным параметром которой будет максимальное значение члена последовательности.
Далее, уже непосредственно для решения задачи определим функцию even_fib_sum
, в которой с помощью list comprehension
найдём сумму всех чётных значений генератора, не привышающих максимальное значение, переданное в единственный параметр функции.
def fibonacci_sequence(limit: int) -> int:
a, b = 0, 1
while a < limit:
yield a
a, b = b, a + b
def even_fib_sum(limit: int) -> int:
return sum([ item for item in fibonacci_sequence(limit) if item % 2 == 0 ])
Чётная последовательность Фибоначчи#
Основная проблема предыдущего решения в том, что мы генерировали все значения последовательности, хотя для решения достаточно лишь чётных по значению. Попробуем взглянуть на чётные члены последовательности:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …
Не забывая, что счёт индексов начинется с нуля, заметим, что все чётные элементы повторяются с постоянным интервалом, каждое третье число Фибоначчи чётное. Выходит, что можно попробовать выразить закономерность для генерации лишь чётных числе Фибоначчи, используя реккурентную формулу. Для этого необходимо выразить через и .
Используя определение последовательности Фибоначчи:
представим себе матрёшку, где каждый член последовательности мы можем раскрыть через сумму двух предыдущих. Совершим серию преобразований:
Итого, мы получили реккурентное выражение исключительно для чётных элементов последовательности Фибоначчи:
Больше нет необходимости в проверке чётности значений, код становится проще и быстрее.
Пример реализации на Python#
Аналогично предыдущему решению, используем генератор для получения последовательности Фибоначчи fibonacci_sequence_even
. В этот раз он будет генерировать лишь чётные значения последовательности, поэтому впишем вместо 0 и 1: 2 и 8, как первые четные элементы и используем реккурентное соотношение, полученое в разборе выше.
Для решения задачи снова определяем функцию even_fib_sum
, суммируя значения генератора, с тем отличием, что больше нет необходимости в проверке чётности.
def fibonacci_sequence_even(limit: int) -> int:
a, b = 2, 8
while a < limit:
yield a
a, b = b, 4 * b + a
def even_fib_sum(limit: int) -> int:
return sum([ item for item in fibonacci_sequence_even(limit) ])