142 Perfect Square Collection.pl 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. #!/usr/bin/perl
  2. # Author: Trizen
  3. # Date: 18 March 2022
  4. # https://github.com/trizen
  5. # Perfect Square Collection
  6. # https://projecteuler.net/problem=142
  7. # Find the smallest x + y + z with integers x > y > z > 0 such that x + y, x − y, x + z, x − z, y + z, y − z are all perfect squares.
  8. # Solution based on the following idea:
  9. # (x+y)*(x-y) = x^2 - y^2
  10. # Since x+y and x-y must be squares, their product is also a square: (x+y)*(x-y) = n^2
  11. # Iterate over n=1..Inf and find the (x,y) solutions to the equation n^2 = x^2 - y^2.
  12. # Then, for each solution (x,y), try to find z, iterating from k=1 to sqrt(y), setting z = y - k^2 and checking if it satisfies the conditions.
  13. # Runtime: ~11 minutes.
  14. use 5.020;
  15. use strict;
  16. use warnings;
  17. use ntheory qw(divisors is_square sqrtint);
  18. use experimental qw(signatures);
  19. sub difference_of_two_squares_solutions ($n) {
  20. my @solutions;
  21. foreach my $divisor (divisors($n)) {
  22. last if $divisor * $divisor >= $n;
  23. my $p = $divisor;
  24. my $q = $n / $divisor;
  25. ($p + $q) % 2 == 0 or next;
  26. my $x = ($q + $p) >> 1;
  27. my $y = ($q - $p) >> 1;
  28. unshift @solutions, [$x, $y];
  29. }
  30. return @solutions;
  31. }
  32. foreach my $k (1 .. 1e9) {
  33. say "Checking: $k";
  34. foreach my $pair (difference_of_two_squares_solutions($k * $k)) {
  35. my ($x, $y) = @$pair;
  36. is_square($x - $y) || next;
  37. is_square($x + $y) || next;
  38. foreach my $n (1 .. sqrtint($y)) {
  39. my $z = ($y - $n * $n);
  40. if (is_square($x + $z) && is_square($x - $z) && is_square($y + $z) && is_square($y - $z)) {
  41. die "Found: sum($x,$y,$z) = ", $x + $y + $z;
  42. }
  43. }
  44. }
  45. }