linear_diophantine_equation.sf 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #!/usr/bin/ruby
  2. # Solve in integers the linear Diophantine equation:
  3. #
  4. # a*x + b*y = n
  5. #
  6. # where a,b,n are given.
  7. # See also:
  8. # https://en.wikipedia.org/wiki/Diophantine_equation
  9. # https://mathworld.wolfram.com/DiophantineEquation.html
  10. func solve(a, b, c) {
  11. var (x, y, z) = gcdext(a, b)
  12. x *= c/z
  13. y *= c/z
  14. return (x, y)
  15. }
  16. var tests = [
  17. [79, 23, 1],
  18. [97, 43, 1],
  19. [43, 97, 1],
  20. [55, 28, 1],
  21. [42, 22, 2],
  22. [79, 23, 10],
  23. [43, 97, 12],
  24. [97, 43, 12],
  25. ]
  26. for a,b,n in tests {
  27. var (x, y) = solve(a, b, n)
  28. assert(x.is_int)
  29. assert(b.is_int)
  30. assert_eq(a*x + b*y, n)
  31. printf("#{a}*x + #{b}*y = %2s --> (x, y) = (%2s, %2s)\n", n, x, y)
  32. }
  33. say "\n>> Extra tests:"
  34. var a = 43*97
  35. var b = 41*57
  36. for n in ([1, 7, 8, 23, 31, 147, 178, 325, 503, 1834]) {
  37. var (x, y) = solve(a, b, n)
  38. assert(x.is_int)
  39. assert(y.is_int)
  40. assert_eq(a*x + b*y, n)
  41. printf("#{a}*x + #{b}*y = %4s --> (x, y) = (%5s, %5s)\n", n, x, y)
  42. }
  43. __END__
  44. 79*x + 23*y = 1 --> (x, y) = ( 7, -24)
  45. 97*x + 43*y = 1 --> (x, y) = ( 4, -9)
  46. 43*x + 97*y = 1 --> (x, y) = (-9, 4)
  47. 55*x + 28*y = 1 --> (x, y) = (-1, 2)
  48. 42*x + 22*y = 2 --> (x, y) = (-1, 2)
  49. 79*x + 23*y = 10 --> (x, y) = (70, -240)
  50. 43*x + 97*y = 12 --> (x, y) = (-108, 48)
  51. 97*x + 43*y = 12 --> (x, y) = (48, -108)
  52. >> Extra tests:
  53. 4171*x + 2337*y = 1 --> (x, y) = ( -302, 539)
  54. 4171*x + 2337*y = 7 --> (x, y) = (-2114, 3773)
  55. 4171*x + 2337*y = 8 --> (x, y) = (-2416, 4312)
  56. 4171*x + 2337*y = 23 --> (x, y) = (-6946, 12397)
  57. 4171*x + 2337*y = 31 --> (x, y) = (-9362, 16709)
  58. 4171*x + 2337*y = 147 --> (x, y) = (-44394, 79233)
  59. 4171*x + 2337*y = 178 --> (x, y) = (-53756, 95942)
  60. 4171*x + 2337*y = 325 --> (x, y) = (-98150, 175175)
  61. 4171*x + 2337*y = 503 --> (x, y) = (-151906, 271117)
  62. 4171*x + 2337*y = 1834 --> (x, y) = (-553868, 988526)