Skip to content

Commit 14b96e6

Browse files
authored
feat(blockchain): add all_diophantine_solutions with type hints & doctests
1 parent c0ad5bb commit 14b96e6

1 file changed

Lines changed: 45 additions & 0 deletions

File tree

blockchain/diophantine_equation.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,48 @@ def extended_gcd(a: int, b: int) -> tuple[int, int, int]:
107107
testmod(name="diophantine_all_soln", verbose=True)
108108
testmod(name="extended_gcd", verbose=True)
109109
testmod(name="greatest_common_divisor", verbose=True)
110+
111+
from __future__ import annotations
112+
113+
def all_diophantine_solutions(a: int, b: int, c: int, n: int = 2) -> list[tuple[int, int]]:
114+
"""
115+
Return up to `n` integer solutions (x, y) to the linear Diophantine equation
116+
a*x + b*y = c using the extended Euclidean algorithm.
117+
118+
Raises:
119+
ValueError: If no integer solutions exist.
120+
121+
Time complexity: O(log(max(|a|, |b|))) to compute one base solution via extended_gcd,
122+
plus O(n) to enumerate `n` solutions.
123+
Space complexity: O(1) beyond the returned list.
124+
125+
Examples
126+
--------
127+
>>> all_diophantine_solutions(10, 6, 14, n=2)
128+
[(-7, 14), (-4, 9)]
129+
>>> all_diophantine_solutions(10, 6, 14, n=4)
130+
[(-7, 14), (-4, 9), (-1, 4), (2, -1)]
131+
>>> all_diophantine_solutions(3, 6, 10, n=1)
132+
Traceback (most recent call last):
133+
...
134+
ValueError: No integer solutions exist for a=3, b=6, c=10
135+
"""
136+
if a == 0 and b == 0:
137+
if c == 0:
138+
return [(0, 0)][: min(1, n)]
139+
raise ValueError("No integer solutions exist for a=0, b=0, c!=0")
140+
141+
g, xg, yg = extended_gcd(abs(a), abs(b))
142+
if c % g != 0:
143+
raise ValueError(f"No integer solutions exist for a={a}, b={b}, c={c}")
144+
145+
# Scale a particular solution to ax + by = c
146+
x0, y0 = xg * (c // g), yg * (c // g)
147+
if a < 0:
148+
x0 = -x0
149+
if b < 0:
150+
y0 = -y0
151+
152+
# General solution: x = x0 + t*(b/g), y = y0 - t*(a/g)
153+
dx, dy = b // g, a // g
154+
return [(x0 + t * dx, y0 - t * dy) for t in range(n)]

0 commit comments

Comments
 (0)