difference_of_three_squares_solutions.pl 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #!/usr/bin/perl
  2. # Daniel "Trizen" Șuteu
  3. # Date: 11 August 2017
  4. # Edit: 26 October 2017
  5. # https://github.com/trizen
  6. # An efficient algorithm for finding solutions to the equation:
  7. #
  8. # x^2 - (x - a)^2 - (x - 2*a)^2 = n
  9. #
  10. # where only `n` is known.
  11. # This algorithm uses the divisors of `n` to generate all the positive integer solutions.
  12. # See also:
  13. # https://projecteuler.net/problem=135
  14. use 5.010;
  15. use strict;
  16. use warnings;
  17. use ntheory qw(divisors);
  18. sub difference_of_three_squares_solutions {
  19. my ($n) = @_;
  20. my @divisors = divisors($n);
  21. my @solutions;
  22. foreach my $divisor (@divisors) {
  23. last if $divisor > sqrt($n);
  24. my $p = $divisor;
  25. my $q = $n / $divisor;
  26. my $k = $q + $p;
  27. ($k % 4 == 0) ? ($k >>= 2) : next;
  28. my $x1 = 3*$k - (($q - $p) >> 1);
  29. my $x2 = 3*$k + (($q - $p) >> 1);
  30. if (($x1 - 2*$k) > 0) {
  31. push @solutions, [$x1, $k];
  32. }
  33. if ($x1 != $x2) {
  34. push @solutions, [$x2, $k];
  35. }
  36. }
  37. return sort { $a->[0] <=> $b->[0] } @solutions;
  38. }
  39. my $n = 900;
  40. my @solutions = difference_of_three_squares_solutions($n);
  41. foreach my $solution (@solutions) {
  42. my $x = $solution->[0];
  43. my $k = $solution->[1];
  44. say "[$x, $k] => $x^2 - ($x - $k)^2 - ($x - 2*$k)^2 = $n";
  45. }
  46. __END__
  47. [35, 17] => 35^2 - (35 - 17)^2 - (35 - 2*17)^2 = 900
  48. [45, 15] => 45^2 - (45 - 15)^2 - (45 - 2*15)^2 = 900
  49. [67, 17] => 67^2 - (67 - 17)^2 - (67 - 2*17)^2 = 900
  50. [115, 25] => 115^2 - (115 - 25)^2 - (115 - 2*25)^2 = 900
  51. [189, 39] => 189^2 - (189 - 39)^2 - (189 - 2*39)^2 = 900
  52. [563, 113] => 563^2 - (563 - 113)^2 - (563 - 2*113)^2 = 900