From 348b81da2bc97765908496f2bedde8307a8e0cbe Mon Sep 17 00:00:00 2001 From: lighting9999 Date: Fri, 3 Oct 2025 15:29:23 +0800 Subject: [PATCH 1/6] fix this py is to slow Problem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Added matrix_power_lucas_number function: · Implements matrix exponentiation algorithm for O(log n) time complexity · Maintains the same interface as existing functions · Includes comprehensive doctests matching the existing patterns 2. Key features: · Uses 2x2 matrix multiplication with fast exponentiation · Handles base cases (n=0, n=1) directly · Proper type annotations for all internal functions · Maintains backward compatibility --- maths/lucas_series.py | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/maths/lucas_series.py b/maths/lucas_series.py index cae6c2815aec..c36046487fc6 100644 --- a/maths/lucas_series.py +++ b/maths/lucas_series.py @@ -55,6 +55,58 @@ def dynamic_lucas_number(n_th_number: int) -> int: return a +def matrix_power_lucas_number(n_th_number: int) -> int: + """ + Returns the nth lucas number using matrix exponentiation + >>> matrix_power_lucas_number(1) + 1 + >>> matrix_power_lucas_number(20) + 15127 + >>> matrix_power_lucas_number(0) + 2 + >>> matrix_power_lucas_number(25) + 167761 + >>> matrix_power_lucas_number(-1.5) + Traceback (most recent call last): + ... + TypeError: matrix_power_lucas_number accepts only integer arguments. + """ + if not isinstance(n_th_number, int): + raise TypeError("matrix_power_lucas_number accepts only integer arguments.") + + if n_th_number == 0: + return 2 + if n_th_number == 1: + return 1 + + def matrix_mult(a: list[list[int]], b: list[list[int]]) -> list[list[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: list[list[int]], power: int) -> list[list[int]]: + # Start with identity matrix + result: list[list[int]] = [[1, 0], [0, 1]] + base = matrix + + while power > 0: + if power % 2 == 1: + result = matrix_mult(result, base) + base = matrix_mult(base, base) + power //= 2 + + return result + + # Lucas number matrix form: [[1, 1], [1, 0]] + base_matrix = [[1, 1], [1, 0]] + powered_matrix = matrix_power(base_matrix, n_th_number - 1) + + # L(n) = powered_matrix[0][0] * L(1) + powered_matrix[0][1] * L(0) + # Where L(1) = 1, L(0) = 2 + return powered_matrix[0][0] * 1 + powered_matrix[0][1] * 2 + + if __name__ == "__main__": from doctest import testmod @@ -64,3 +116,5 @@ def dynamic_lucas_number(n_th_number: int) -> int: print(" ".join(str(recursive_lucas_number(i)) for i in range(n))) print("\nUsing dynamic function to calculate lucas series:") print(" ".join(str(dynamic_lucas_number(i)) for i in range(n))) + print("\nUsing matrix exponentiation to calculate lucas series:") + print(" ".join(str(matrix_power_lucas_number(i)) for i in range(n))) From 2e27079f51e4082d08fc05a8d31d787ef359e216 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 07:33:47 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- maths/lucas_series.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/maths/lucas_series.py b/maths/lucas_series.py index c36046487fc6..a82ef19b21fc 100644 --- a/maths/lucas_series.py +++ b/maths/lucas_series.py @@ -73,35 +73,41 @@ def matrix_power_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("matrix_power_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + def matrix_mult(a: list[list[int]], b: list[list[int]]) -> list[list[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]], + [ + 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: list[list[int]], power: int) -> list[list[int]]: # Start with identity matrix result: list[list[int]] = [[1, 0], [0, 1]] base = matrix - + while power > 0: if power % 2 == 1: result = matrix_mult(result, base) base = matrix_mult(base, base) power //= 2 - + return result - + # Lucas number matrix form: [[1, 1], [1, 0]] base_matrix = [[1, 1], [1, 0]] powered_matrix = matrix_power(base_matrix, n_th_number - 1) - + # L(n) = powered_matrix[0][0] * L(1) + powered_matrix[0][1] * L(0) # Where L(1) = 1, L(0) = 2 return powered_matrix[0][0] * 1 + powered_matrix[0][1] * 2 From 87630a250b9387651b8880d40f11484f1bb112d2 Mon Sep 17 00:00:00 2001 From: lighting9999 Date: Fri, 3 Oct 2025 15:47:32 +0800 Subject: [PATCH 3/6] change lucas_series.py --- maths/lucas_series.py | 132 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 107 insertions(+), 25 deletions(-) diff --git a/maths/lucas_series.py b/maths/lucas_series.py index a82ef19b21fc..a2d8c9a67ed5 100644 --- a/maths/lucas_series.py +++ b/maths/lucas_series.py @@ -2,6 +2,10 @@ https://en.wikipedia.org/wiki/Lucas_number """ +import functools +import math +from typing import Dict + def recursive_lucas_number(n_th_number: int) -> int: """ @@ -21,14 +25,17 @@ def recursive_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("recursive_lucas_number accepts only integer arguments.") - if n_th_number == 0: - return 2 - if n_th_number == 1: - return 1 - - return recursive_lucas_number(n_th_number - 1) + recursive_lucas_number( - n_th_number - 2 - ) + + # Use memoization to cache results and avoid redundant calculations + @functools.lru_cache(maxsize=None) + def _recursive_lucas(n: int) -> int: + if n == 0: + return 2 + if n == 1: + return 1 + return _recursive_lucas(n - 1) + _recursive_lucas(n - 2) + + return _recursive_lucas(n_th_number) def dynamic_lucas_number(n_th_number: int) -> int: @@ -49,10 +56,17 @@ def dynamic_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("dynamic_lucas_number accepts only integer arguments.") + + if n_th_number == 0: + return 2 + if n_th_number == 1: + return 1 + a, b = 2, 1 - for _ in range(n_th_number): + for _ in range(2, n_th_number + 1): a, b = b, a + b - return a + + return b def matrix_power_lucas_number(n_th_number: int) -> int: @@ -73,46 +87,110 @@ def matrix_power_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("matrix_power_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + def matrix_mult(a: list[list[int]], b: list[list[int]]) -> list[list[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], - ], + [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: list[list[int]], power: int) -> list[list[int]]: # Start with identity matrix result: list[list[int]] = [[1, 0], [0, 1]] base = matrix - + while power > 0: if power % 2 == 1: result = matrix_mult(result, base) base = matrix_mult(base, base) power //= 2 - + return result - + # Lucas number matrix form: [[1, 1], [1, 0]] base_matrix = [[1, 1], [1, 0]] powered_matrix = matrix_power(base_matrix, n_th_number - 1) - + # L(n) = powered_matrix[0][0] * L(1) + powered_matrix[0][1] * L(0) # Where L(1) = 1, L(0) = 2 return powered_matrix[0][0] * 1 + powered_matrix[0][1] * 2 +def closed_form_lucas_number(n_th_number: int) -> int: + """ + Returns the nth lucas number using the closed-form formula (Binet's formula) + >>> closed_form_lucas_number(1) + 1 + >>> closed_form_lucas_number(20) + 15127 + >>> closed_form_lucas_number(0) + 2 + >>> closed_form_lucas_number(25) + 167761 + >>> closed_form_lucas_number(-1.5) + Traceback (most recent call last): + ... + TypeError: closed_form_lucas_number accepts only integer arguments. + """ + if not isinstance(n_th_number, int): + raise TypeError("closed_form_lucas_number accepts only integer arguments.") + + if n_th_number == 0: + return 2 + if n_th_number == 1: + return 1 + + # Golden ratio + phi = (1 + math.sqrt(5)) / 2 + # Conjugate of golden ratio + psi = (1 - math.sqrt(5)) / 2 + + # Lucas number closed form: L(n) = phi^n + psi^n + return round(phi**n_th_number + psi**n_th_number) + + +# Global cache for performance optimization +_lucas_cache: Dict[int, int] = {0: 2, 1: 1} + + + +def cached_lucas_number(n_th_number: int) -> int: + """ + Returns the nth lucas number using a cached approach for optimal performance + >>> cached_lucas_number(1) + 1 + >>> cached_lucas_number(20) + 15127 + >>> cached_lucas_number(0) + 2 + >>> cached_lucas_number(25) + 167761 + >>> cached_lucas_number(-1.5) + Traceback (most recent call last): + ... + TypeError: cached_lucas_number accepts only integer arguments. + """ + if not isinstance(n_th_number, int): + raise TypeError("cached_lucas_number accepts only integer arguments.") + + if n_th_number in _lucas_cache: + return _lucas_cache[n_th_number] + + # Calculate using the fastest method for uncached values + if n_th_number < 70: # For smaller values, closed form is efficient + result = closed_form_lucas_number(n_th_number) + else: # For larger values, matrix exponentiation is more stable + result = matrix_power_lucas_number(n_th_number) + + _lucas_cache[n_th_number] = result + return result + + if __name__ == "__main__": from doctest import testmod @@ -124,3 +202,7 @@ def matrix_power(matrix: list[list[int]], power: int) -> list[list[int]]: print(" ".join(str(dynamic_lucas_number(i)) for i in range(n))) print("\nUsing matrix exponentiation to calculate lucas series:") print(" ".join(str(matrix_power_lucas_number(i)) for i in range(n))) + print("\nUsing closed-form formula to calculate lucas series:") + print(" ".join(str(closed_form_lucas_number(i)) for i in range(n))) + print("\nUsing cached function to calculate lucas series:") + print(" ".join(str(cached_lucas_number(i)) for i in range(n))) \ No newline at end of file From c32742c8b49b86e5c2f25ad49e7d33b033f756ff Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 07:48:52 +0000 Subject: [PATCH 4/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- maths/lucas_series.py | 49 ++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/maths/lucas_series.py b/maths/lucas_series.py index a2d8c9a67ed5..f200f4ebe78f 100644 --- a/maths/lucas_series.py +++ b/maths/lucas_series.py @@ -25,7 +25,7 @@ def recursive_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("recursive_lucas_number accepts only integer arguments.") - + # Use memoization to cache results and avoid redundant calculations @functools.lru_cache(maxsize=None) def _recursive_lucas(n: int) -> int: @@ -34,7 +34,7 @@ def _recursive_lucas(n: int) -> int: if n == 1: return 1 return _recursive_lucas(n - 1) + _recursive_lucas(n - 2) - + return _recursive_lucas(n_th_number) @@ -56,16 +56,16 @@ def dynamic_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("dynamic_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + a, b = 2, 1 for _ in range(2, n_th_number + 1): a, b = b, a + b - + return b @@ -87,35 +87,41 @@ def matrix_power_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("matrix_power_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + def matrix_mult(a: list[list[int]], b: list[list[int]]) -> list[list[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]], + [ + 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: list[list[int]], power: int) -> list[list[int]]: # Start with identity matrix result: list[list[int]] = [[1, 0], [0, 1]] base = matrix - + while power > 0: if power % 2 == 1: result = matrix_mult(result, base) base = matrix_mult(base, base) power //= 2 - + return result - + # Lucas number matrix form: [[1, 1], [1, 0]] base_matrix = [[1, 1], [1, 0]] powered_matrix = matrix_power(base_matrix, n_th_number - 1) - + # L(n) = powered_matrix[0][0] * L(1) + powered_matrix[0][1] * L(0) # Where L(1) = 1, L(0) = 2 return powered_matrix[0][0] * 1 + powered_matrix[0][1] * 2 @@ -139,17 +145,17 @@ def closed_form_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("closed_form_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + # Golden ratio phi = (1 + math.sqrt(5)) / 2 # Conjugate of golden ratio psi = (1 - math.sqrt(5)) / 2 - + # Lucas number closed form: L(n) = phi^n + psi^n return round(phi**n_th_number + psi**n_th_number) @@ -158,7 +164,6 @@ def closed_form_lucas_number(n_th_number: int) -> int: _lucas_cache: Dict[int, int] = {0: 2, 1: 1} - def cached_lucas_number(n_th_number: int) -> int: """ Returns the nth lucas number using a cached approach for optimal performance @@ -177,16 +182,16 @@ def cached_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("cached_lucas_number accepts only integer arguments.") - + if n_th_number in _lucas_cache: return _lucas_cache[n_th_number] - + # Calculate using the fastest method for uncached values if n_th_number < 70: # For smaller values, closed form is efficient result = closed_form_lucas_number(n_th_number) else: # For larger values, matrix exponentiation is more stable result = matrix_power_lucas_number(n_th_number) - + _lucas_cache[n_th_number] = result return result @@ -205,4 +210,4 @@ def cached_lucas_number(n_th_number: int) -> int: print("\nUsing closed-form formula to calculate lucas series:") print(" ".join(str(closed_form_lucas_number(i)) for i in range(n))) print("\nUsing cached function to calculate lucas series:") - print(" ".join(str(cached_lucas_number(i)) for i in range(n))) \ No newline at end of file + print(" ".join(str(cached_lucas_number(i)) for i in range(n))) From eed5bc7ca7376fca2e8c55671eed8d6640a09581 Mon Sep 17 00:00:00 2001 From: lighting9999 Date: Fri, 3 Oct 2025 15:52:02 +0800 Subject: [PATCH 5/6] Change lucas_series.py --- maths/lucas_series.py | 53 +++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/maths/lucas_series.py b/maths/lucas_series.py index f200f4ebe78f..00399dd5397d 100644 --- a/maths/lucas_series.py +++ b/maths/lucas_series.py @@ -4,7 +4,6 @@ import functools import math -from typing import Dict def recursive_lucas_number(n_th_number: int) -> int: @@ -25,16 +24,16 @@ def recursive_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("recursive_lucas_number accepts only integer arguments.") - + # Use memoization to cache results and avoid redundant calculations - @functools.lru_cache(maxsize=None) + @functools.cache def _recursive_lucas(n: int) -> int: if n == 0: return 2 if n == 1: return 1 return _recursive_lucas(n - 1) + _recursive_lucas(n - 2) - + return _recursive_lucas(n_th_number) @@ -56,16 +55,16 @@ def dynamic_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("dynamic_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + a, b = 2, 1 for _ in range(2, n_th_number + 1): a, b = b, a + b - + return b @@ -87,41 +86,35 @@ def matrix_power_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("matrix_power_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + def matrix_mult(a: list[list[int]], b: list[list[int]]) -> list[list[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], - ], + [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: list[list[int]], power: int) -> list[list[int]]: # Start with identity matrix result: list[list[int]] = [[1, 0], [0, 1]] base = matrix - + while power > 0: if power % 2 == 1: result = matrix_mult(result, base) base = matrix_mult(base, base) power //= 2 - + return result - + # Lucas number matrix form: [[1, 1], [1, 0]] base_matrix = [[1, 1], [1, 0]] powered_matrix = matrix_power(base_matrix, n_th_number - 1) - + # L(n) = powered_matrix[0][0] * L(1) + powered_matrix[0][1] * L(0) # Where L(1) = 1, L(0) = 2 return powered_matrix[0][0] * 1 + powered_matrix[0][1] * 2 @@ -145,23 +138,23 @@ def closed_form_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("closed_form_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + # Golden ratio phi = (1 + math.sqrt(5)) / 2 # Conjugate of golden ratio psi = (1 - math.sqrt(5)) / 2 - + # Lucas number closed form: L(n) = phi^n + psi^n return round(phi**n_th_number + psi**n_th_number) # Global cache for performance optimization -_lucas_cache: Dict[int, int] = {0: 2, 1: 1} +_lucas_cache: dict[int, int] = {0: 2, 1: 1} def cached_lucas_number(n_th_number: int) -> int: @@ -182,16 +175,16 @@ def cached_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("cached_lucas_number accepts only integer arguments.") - + if n_th_number in _lucas_cache: return _lucas_cache[n_th_number] - + # Calculate using the fastest method for uncached values if n_th_number < 70: # For smaller values, closed form is efficient result = closed_form_lucas_number(n_th_number) else: # For larger values, matrix exponentiation is more stable result = matrix_power_lucas_number(n_th_number) - + _lucas_cache[n_th_number] = result return result @@ -210,4 +203,4 @@ def cached_lucas_number(n_th_number: int) -> int: print("\nUsing closed-form formula to calculate lucas series:") print(" ".join(str(closed_form_lucas_number(i)) for i in range(n))) print("\nUsing cached function to calculate lucas series:") - print(" ".join(str(cached_lucas_number(i)) for i in range(n))) + print(" ".join(str(cached_lucas_number(i)) for i in range(n))) \ No newline at end of file From c36bcc703ce8006a420d1ae97f9a0f97fc0a8702 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 3 Oct 2025 07:52:52 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- maths/lucas_series.py | 48 ++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/maths/lucas_series.py b/maths/lucas_series.py index 00399dd5397d..640a6c83b249 100644 --- a/maths/lucas_series.py +++ b/maths/lucas_series.py @@ -24,7 +24,7 @@ def recursive_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("recursive_lucas_number accepts only integer arguments.") - + # Use memoization to cache results and avoid redundant calculations @functools.cache def _recursive_lucas(n: int) -> int: @@ -33,7 +33,7 @@ def _recursive_lucas(n: int) -> int: if n == 1: return 1 return _recursive_lucas(n - 1) + _recursive_lucas(n - 2) - + return _recursive_lucas(n_th_number) @@ -55,16 +55,16 @@ def dynamic_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("dynamic_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + a, b = 2, 1 for _ in range(2, n_th_number + 1): a, b = b, a + b - + return b @@ -86,35 +86,41 @@ def matrix_power_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("matrix_power_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + def matrix_mult(a: list[list[int]], b: list[list[int]]) -> list[list[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]], + [ + 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: list[list[int]], power: int) -> list[list[int]]: # Start with identity matrix result: list[list[int]] = [[1, 0], [0, 1]] base = matrix - + while power > 0: if power % 2 == 1: result = matrix_mult(result, base) base = matrix_mult(base, base) power //= 2 - + return result - + # Lucas number matrix form: [[1, 1], [1, 0]] base_matrix = [[1, 1], [1, 0]] powered_matrix = matrix_power(base_matrix, n_th_number - 1) - + # L(n) = powered_matrix[0][0] * L(1) + powered_matrix[0][1] * L(0) # Where L(1) = 1, L(0) = 2 return powered_matrix[0][0] * 1 + powered_matrix[0][1] * 2 @@ -138,17 +144,17 @@ def closed_form_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("closed_form_lucas_number accepts only integer arguments.") - + if n_th_number == 0: return 2 if n_th_number == 1: return 1 - + # Golden ratio phi = (1 + math.sqrt(5)) / 2 # Conjugate of golden ratio psi = (1 - math.sqrt(5)) / 2 - + # Lucas number closed form: L(n) = phi^n + psi^n return round(phi**n_th_number + psi**n_th_number) @@ -175,16 +181,16 @@ def cached_lucas_number(n_th_number: int) -> int: """ if not isinstance(n_th_number, int): raise TypeError("cached_lucas_number accepts only integer arguments.") - + if n_th_number in _lucas_cache: return _lucas_cache[n_th_number] - + # Calculate using the fastest method for uncached values if n_th_number < 70: # For smaller values, closed form is efficient result = closed_form_lucas_number(n_th_number) else: # For larger values, matrix exponentiation is more stable result = matrix_power_lucas_number(n_th_number) - + _lucas_cache[n_th_number] = result return result @@ -203,4 +209,4 @@ def cached_lucas_number(n_th_number: int) -> int: print("\nUsing closed-form formula to calculate lucas series:") print(" ".join(str(closed_form_lucas_number(i)) for i in range(n))) print("\nUsing cached function to calculate lucas series:") - print(" ".join(str(cached_lucas_number(i)) for i in range(n))) \ No newline at end of file + print(" ".join(str(cached_lucas_number(i)) for i in range(n)))