Last Digit of the Sum of Fibonacci Numbers

Another couple of problems in the same lot of the one previously discussed. Now we have to calculate the last digit of the (full or partial) sum of Fibonacci numbers.

Also these problems are presented in the the edX MOOC Algs200x Algorithmic Design and Techniques by the UC San Diego, week 2, so I suggest you to give them a try and then comparing your solutions with my python scripts.

Last Digit of the Sum of Fibonacci Numbers

Given an integer 𝑛, find the last digit of the sum 𝐹0 + 𝐹1 + · · · + 𝐹𝑛.

Considering that n could be as big as 10^14, the naive solution of summing up all the Fibonacci numbers as long as we calculate them is leading too slowly to the result.

We'd better take notice of the hint about experimenting a bit with small test cases looking if we can extrapolate anything interesting. Actually, after a while I find out that the sum of the first n Fibonacci number is just one shorter than the sum of Fibonacci of n + 2. Another useful consideration is that, since we need just the last digit, we could use the result of the previous exercise and limit our loop following the Pisano period.

Putting all together, this is my solution:
PISANO = 60  # 1


def solution(number):
    if number < 2:
        return number

    number %= PISANO

    results = [1, 1]
    for _ in range(number):
        results.append((results[-1] + results[-2]) % 10)  # 2

    return (results[-1] - 1) % 10  # 3
1. Instead of giving the result for the requested number, I check the modulo 60, being that the Pisano period for 10.
2. I'm not interested in the actual Fibonacci number, just it's last digit, so here I apply modulo 10 to the brand new calculated one. In this way I avoid scaling to big numbers.
3. I apply the modulo operator once again to get rid of the unfortunate case of possibly negative results.

Naive, Pisano script, and test case for both, are on GitHub.

Last Digit of the Partial Sum of Fibonacci Numbers

Given two non-negative integers π‘š and 𝑛, where π‘š ≤ 𝑛, find the last digit of the sum πΉπ‘š + πΉπ‘š+1 + ... + 𝐹𝑛.

The trick used in the previous problem won't work here, and I couldn't think of any similar clever approach. So I resorted to make full use of Pisano, hoping that it was enough.
PISANO = 60


def solution(left, right):
    assert not left > right  # 1

    fib_mods = [0, 1]  # 2
    for _ in range(PISANO - 2):
        fib_mods.append((fib_mods[-1] + fib_mods[-2]) % 10)

    left %= PISANO  # 3
    right %= PISANO
    if right < left:
        right += PISANO

    result = 0
    for i in range(left, right + 1):
        result += fib_mods[i % PISANO]  # 4
    return result % 10  # 5
1. Not strictly required by the problem, where we can assume the input data is clean.
2. I fill this list with all the Fibonacci number modulo 10 in the range of the Pisano period.
3. I don't need to loop on all the actual requested numbers, I can safely stay in the limit of the Pisano period. With one major caveat, the right limit should not become smaller that left.
4. Loop on the interval, ensuring that I stay in the Pisano limits.
5. Return the last digit of the sum, as required.

Also for this problem I have pushed naive, Pisano script, and test case for both, on GitHub. See the github folder for all the stuff about week 2 exercises.

No comments:

Post a Comment