@@ -100,6 +100,64 @@ def extended_gcd(a: int, b: int) -> tuple[int, int, int]:
100100 return (d , x , y )
101101
102102
103+ def all_diophantine_solutions (
104+ a : int ,
105+ b : int ,
106+ c : int ,
107+ n : int = 2 ,
108+ ) -> list [tuple [int , int ]]:
109+ """
110+ Return up to `n` integer solutions (x, y) to the linear Diophantine equation
111+ a*x + b*y = c using the extended Euclidean algorithm.
112+
113+ Raises
114+ ------
115+ ValueError
116+ If no integer solutions exist.
117+
118+ Time complexity
119+ ---------------
120+ O(log(max(|a|, |b|))) to compute a base solution using extended_gcd;
121+ plus O(n) to enumerate `n` solutions.
122+
123+ Space complexity
124+ ----------------
125+ O(1) beyond the returned list.
126+
127+ Examples
128+ --------
129+ >>> all_diophantine_solutions(10, 6, 14, n=2)
130+ [(-7, 14), (-4, 9)]
131+ >>> all_diophantine_solutions(10, 6, 14, n=4)
132+ [(-7, 14), (-4, 9), (-1, 4), (2, -1)]
133+ >>> all_diophantine_solutions(3, 6, 10, n=1)
134+ Traceback (most recent call last):
135+ ...
136+ ValueError: No integer solutions exist for a=3, b=6, c=10
137+ """
138+ if a == 0 and b == 0 :
139+ if c == 0 :
140+ # Infinite solutions; return one canonical solution.
141+ return [(0 , 0 )][: min (1 , n )]
142+ raise ValueError ("No integer solutions exist for a=0, b=0, c!=0" )
143+
144+ g , xg , yg = extended_gcd (abs (a ), abs (b ))
145+ if c % g != 0 :
146+ msg = f"No integer solutions exist for a={ a } , b={ b } , c={ c } "
147+ raise ValueError (msg )
148+
149+ # Scale a particular solution to ax + by = c
150+ x0 , y0 = xg * (c // g ), yg * (c // g )
151+ if a < 0 :
152+ x0 = - x0
153+ if b < 0 :
154+ y0 = - y0
155+
156+ # General solution: x = x0 + t*(b/g), y = y0 - t*(a/g)
157+ dx , dy = b // g , a // g
158+ return [(x0 + t * dx , y0 - t * dy ) for t in range (n )]
159+
160+
103161if __name__ == "__main__" :
104162 from doctest import testmod
105163
0 commit comments