0

This is my code for project Euler #2. The problem is : Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

from functools import lru_cache


@lru_cache(maxsize=1000000)
def fibonacci_memo(input_value):
  global value
  fibonacci_cache = {}
  if input_value in fibonacci_cache:
    return fibonacci_cache[input_value]
  if input_value == 0:
    value = 1
  elif input_value == 1:
    value = 1
  elif input_value > 1:
    value = fibonacci_memo(input_value - 1) + 
    fibonacci_memo(input_value - 2)
    fibonacci_cache[input_value] = value
    return value


  @lru_cache(maxsize=1000000)
  def sumOfFib():
   SUM = 0
  for n in range(32):
    while fibonacci_memo(n) < 4000000:
        if fibonacci_memo(n) % 2 == 0:
            SUM += fibonacci_memo(n)
   return SUM


   print(sumOfFib())

This program is not efficient enough, need help.

  • Please include the problem – Michael Bianconi Jun 28 '20 at 03:53
  • 1
    You have no global variable called `value`? – Michael Bianconi Jun 28 '20 at 03:53
  • 1
    What happens to `value` when `input_value` is `0`, which is the first value you pass in? Also, your last edit looks like it over-indented the `return`. – Mark Jun 28 '20 at 03:54
  • I changed the value to 0 as initial but now I get this as an error: Traceback (most recent call last): File "/Users/randomkingrd/PycharmProjects/Problem solving/Euler.py", line 38, in print(sumOfFib()) File "/Users/randomkingrd/PycharmProjects/Problem solving/Euler.py", line 32, in sumOfFib while fibonacci_memo(n) < 4000000: KeyboardInterrupt – RandomKingRD Jun 28 '20 at 04:04
  • I think that the script was running too long and you pressed CTRL+C. I suggest you try solving with dynamic programming and maybe move the check inside the fibonacci_memo to avoid the computation(remember that the result is less than 4M for input_value < 31 with initial values 1 1). – Federico A. Jun 28 '20 at 04:46
  • I used memoization. Shouldn't it work ? – RandomKingRD Jun 28 '20 at 04:55

3 Answers3

1

EDITED:

As @Mark suggests, the "value" variable must be declared somewhere before using/returning it. If you want to have a global variable, it has to be declared in a global scope, outside the function.

Check Here the usage of the global variables.

from functools import lru_cache

value = 0
@lru_cache(maxsize=1000000)
def fibonacci_memo(input_value):
    global value
    fibonacci_cache = {}
    if input_value in fibonacci_cache:
        return fibonacci_cache[input_value]
    if input_value == 1:
        value = 1
    elif input_value == 2:
        value = 1
    elif input_value > 2:
        value = fibonacci_memo(input_value - 1) + fibonacci_memo(input_value - 2)
        fibonacci_cache[input_value] = value
    return value


def sumOfFib():
    SUM = 0
    for n in range(501):
        while fibonacci_memo(n) < 4000000:
            if fibonacci_memo(n) % 2 == 0:
                SUM += fibonacci_memo(n)
    return SUM


print(sumOfFib())

Federico A.
  • 256
  • 2
  • 8
1

TL;DR Establish the global value variable at the top of your function.

"""Disclaim: this is a highly abbreviated interpretation for simplicity sake.

The global keyword is attempting to import into a local scope, a variable called value from the global (name) space, but it has not been established in that namespace yet.

Xinthral
  • 438
  • 2
  • 10
0

The fibonacci sequence has even values every 3 elements. So you could make a generator function for fibonacci numbers up to a certain value, then slice the result to get every third entry and sum the result:

# fibonacci generator

def fibo(n):
    a,b = 0,1
    while a<=n:
        yield a
        a,b = b,a+b

# fibonacci numbers less or equal to 4,000,000:

print(*fibo(4000000))
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765    
10946 17711 28657 46368 75025 121393 196418 317811 514229 832040 
1346269 2178309 3524578

# slicing the generated values to get every third entry

from itertools import islice
print(*islice(fibo(4000000),0,None,3))

0 2 8 34 144 610 2584 10946 46368 196418 832040 3524578

# total of the sliced values:

print(sum(islice(fibo(4000000),0,None,3)))        
4613732            

You really don't need to use an LRU or memoizing to obtain this result. BTW, the modern version of the fibonacci sequence actually starts at 0,1 but that wont change the answer.

You could also make a specialized generator that only returns even values of the sequence and use that in a sum():

def evenFibo(n):
    a,b=0,1
    while a<=n:
        yield a
        a,b = b,a+b  # these 3 lines could 
        a,b = b,a+b  # be replaced by
        a,b = b,a+b  # a,b = a+2*b,2*a+3*b

print(sum(evenFibo(4000000))
Alain T.
  • 40,517
  • 4
  • 31
  • 51