fibonacci-backend / app /algorithms.py
Adisri99's picture
Upload 9 files
02518d0 verified
from __future__ import annotations
from typing import Callable, Tuple
def _negafib_sign(n: int) -> int:
abs_n = abs(n)
return 1 if abs_n % 2 == 1 else -1
def fibonacci_iterative(n: int) -> int:
if n == 0:
return 0
abs_n = abs(n)
a, b = 0, 1
for _ in range(abs_n):
a, b = b, a + b
if n > 0:
return a
return _negafib_sign(n) * a
def _fast_doubling_core(n: int) -> Tuple[int, int]:
if n == 0:
return 0, 1
a, b = _fast_doubling_core(n // 2)
c = a * ((2 * b) - a)
d = a * a + b * b
if n % 2 == 0:
return c, d
return d, c + d
def fibonacci_fast_doubling(n: int) -> int:
if n == 0:
return 0
abs_n = abs(n)
value, _ = _fast_doubling_core(abs_n)
if n > 0:
return value
return _negafib_sign(n) * value
def _matrix_multiply(
a: tuple[tuple[int, int], tuple[int, int]],
b: tuple[tuple[int, int], tuple[int, int]],
) -> tuple[tuple[int, int], tuple[int, int]]:
return (
(
a[0][0] * b[0][0] + a[0][1] * b[1][0],
a[0][0] * b[0][1] + a[0][1] * b[1][1],
),
(
a[1][0] * b[0][0] + a[1][1] * b[1][0],
a[1][0] * b[0][1] + a[1][1] * b[1][1],
),
)
def _matrix_power(
matrix: tuple[tuple[int, int], tuple[int, int]],
exponent: int,
) -> tuple[tuple[int, int], tuple[int, int]]:
result = ((1, 0), (0, 1))
base = matrix
exp = exponent
while exp > 0:
if exp % 2 == 1:
result = _matrix_multiply(result, base)
base = _matrix_multiply(base, base)
exp //= 2
return result
def fibonacci_matrix(n: int) -> int:
if n == 0:
return 0
abs_n = abs(n)
q_matrix = ((1, 1), (1, 0))
powered = _matrix_power(q_matrix, abs_n - 1)
value = powered[0][0]
if n > 0:
return value
return _negafib_sign(n) * value
def get_algorithm(name: str) -> Callable[[int], int]:
algorithms: dict[str, Callable[[int], int]] = {
"iterative": fibonacci_iterative,
"fast_doubling": fibonacci_fast_doubling,
"matrix": fibonacci_matrix,
}
if name not in algorithms:
raise ValueError(f"Unsupported algorithm: {name}")
return algorithms[name]
def generate_range(start: int, end: int, algorithm: str) -> list[int]:
if start >= end:
raise ValueError("start must be less than end")
fib = get_algorithm(algorithm)
return [fib(i) for i in range(start, end)]
def generate_positive_range_optimized(start: int, end: int) -> list[int]:
if start < 0 or end < 0:
raise ValueError("optimized range requires non negative indices")
if start >= end:
raise ValueError("start must be less than end")
if end == 1:
return [0] if start == 0 else []
values = [0, 1]
while len(values) < end:
values.append(values[-1] + values[-2])
return values[start:end]