Last active
December 15, 2021 23:45
-
-
Save Diapolo10/e9ea58cb8fe35f6c2da51d623d86bab1 to your computer and use it in GitHub Desktop.
Order N Fibonacci sequence generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import deque | |
from typing import Generator | |
import warnings | |
def n_fibonacci(n: int = 2) -> Generator[int, None, None]: | |
""" | |
Returns a generator that yields the values of a Fibonacci sequence of a given 'base'. | |
When `n == 0`, the returned sequence simplifies to an infinite sequence of `0`. | |
When `n == 1`, the returned sequence simplifies to an infinite sequence of `1`. | |
When `n == 2`, the returned sequence is a normal Fibonacci sequence. | |
When `n == 3`, the returned sequence is a Tribonacci sequence. | |
For higher values of `n`, the respective "N-bonacci" sequence is returned. | |
The value of `n` is not upper-bound by the function. | |
Functionality based on: https://oeis.org/wiki/N-bonacci_numbers | |
Examples: | |
fib = n_fibonacci() | |
print([next(fib) for _ in range(10)]) # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] | |
trib = n_fibonacci(3) | |
print([next(trib) for _ in range(10)]) # [0, 0, 1, 1, 2, 4, 7, 13, 24, 44] | |
""" | |
if n < 0: | |
raise ValueError("Fibonacci base cannot be negative") | |
elif n < 2: | |
warnings.warn(f"Fibonacci sequence simplified to an infinite sequence of `{n}`", UserWarning) | |
vals = [0 for _ in range(n-1)] + [1 if n else 0] | |
while True: | |
yield vals[0] | |
vals[:n-1], vals[n-1] = vals[1:], sum(vals) | |
def deque_n_fibonacci(n: int = 2) -> Generator[int, None, None]: | |
""" | |
A variant of n_fibonacci that uses a deque instead of a list | |
""" | |
if n < 0: | |
raise ValueError("Fibonacci base cannot be negative") | |
elif n < 2: | |
warnings.warn(f"Fibonacci sequence simplified to an infinite sequence of `{n}`", UserWarning) | |
vals = deque([0 for _ in range(n-1)] + [1 if n else 0], maxlen=n) | |
while True: | |
yield vals[0] | |
vals.append(sum(vals)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on quick benchmarks, the deque version is between 15-30% faster for the first 1000 values, depending on the size of
n
. At around 100000 values, the original version performs better.range
was used withzip
to limit the number of values generated, andlist
to force the lazy evaluation to be run.