prog_heuristic.pl 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #!/usr/bin/perl
  2. # Efficient algorithm for generating sub-unit squares.
  3. # A sub-unit square is a square number that remains a square after having a 1 subtracted from each digit in the square.
  4. # See also:
  5. # https://oeis.org/A061844
  6. # https://rosettacode.org/wiki/Sub-unit_squares
  7. # Checked up to (10^167 - 1)/9.
  8. # Checked all n <= 352 with sigma0() <= 10^8.
  9. # Checked all even n <= 692 (except 664, 692) with sigma0() <= 10^8.
  10. use 5.036;
  11. use ntheory qw(:all);
  12. use Math::GMPz;
  13. use Math::Prime::Util::GMP qw();
  14. use Math::Sidef qw();
  15. use Math::AnyNum qw();
  16. $Sidef::Types::Number::Number::VERBOSE = '1';
  17. $Sidef::Types::Number::Number::USE_FACTORDB = '1';
  18. sub difference_of_two_squares_solutions ($n, $callback) { # solutions x to x^2 - y^2 = n
  19. state $limit = Math::GMPz::Rmpz_init();
  20. Math::GMPz::Rmpz_sqrt($limit, $n);
  21. #Math::Sidef::sigma0($n) <= 1e8 or return;
  22. my @factors = map { "$_" } grep { $$_ <= $limit } Math::Sidef::factor($n);
  23. state $p = Math::GMPz::Rmpz_init();
  24. state $q = Math::GMPz::Rmpz_init();
  25. state $t = Math::GMPz::Rmpz_init();
  26. foreach my $k (0 .. scalar(@factors)) {
  27. my $comb = binomial(scalar(@factors), $k);
  28. if ($comb > 1e8) {
  29. next; # too many combinations
  30. }
  31. if ($comb > 1e5) {
  32. say "Combinations: (", scalar(@factors), ", $k) == $comb";
  33. }
  34. forcomb {
  35. Math::GMPz::Rmpz_set_str($p, Math::Prime::Util::GMP::vecprod(@factors[@_]), 10);
  36. if (Math::GMPz::Rmpz_cmp($p, $limit) <= 0) {
  37. Math::GMPz::Rmpz_div($q, $n, $p);
  38. Math::GMPz::Rmpz_add($t, $p, $q);
  39. if (Math::GMPz::Rmpz_even_p($t)) {
  40. Math::GMPz::Rmpz_div_2exp($t, $t, 1);
  41. $callback->($t);
  42. }
  43. }
  44. }
  45. scalar(@factors), $k;
  46. }
  47. }
  48. my $N = 1000; # how many terms to compute
  49. my %seen = (1 => 1);
  50. my $index = 1;
  51. say($index, ': ', 1);
  52. for (my $n = 694 ; ; $n += 2) {
  53. my $r = (Math::GMPz->new(10)**$n - 1) / 9;
  54. my $t = Math::GMPz::Rmpz_init();
  55. my $xsqr = Math::GMPz::Rmpz_init();
  56. difference_of_two_squares_solutions(
  57. $r,
  58. sub ($x) {
  59. Math::GMPz::Rmpz_mul($xsqr, $x, $x);
  60. my $str = Math::GMPz::Rmpz_get_str($xsqr, 10);
  61. return if (substr($str, 0, 1) eq '1');
  62. return if (index($str, '0') != -1);
  63. my @d = split(//, $str);
  64. Math::GMPz::Rmpz_set_str($t, join('', map { $_ - 1 } @d), 10);
  65. Math::GMPz::Rmpz_perfect_square_p($t) || return;
  66. if (!$seen{$xsqr}++) {
  67. die "\nNew term found: $xsqr\n\n";
  68. #say("\n", ++$index, ': ', $xsqr, "\n");
  69. exit if ($index >= $N);
  70. }
  71. }
  72. );
  73. }
  74. __END__
  75. 1: 1
  76. 2: 36
  77. 3: 3136
  78. 4: 24336
  79. 5: 5973136
  80. 6: 71526293136
  81. 7: 318723477136
  82. 8: 264779654424693136
  83. 9: 24987377153764853136
  84. 10: 31872399155963477136
  85. 11: 58396845218255516736
  86. 12: 517177921565478376336
  87. 13: 252815272791521979771662766736
  88. 14: 518364744896318875336864648336
  89. 15: 554692513628187865132829886736
  90. 16: 658424734191428581711475835136
  91. 17: 672475429414871757619952152336
  92. 18: 694688876763154697414122245136
  93. 19: 711197579293752874333735845136
  94. 20: 975321699545235187287523246336
  95. 21: 23871973274358556957126877486736
  96. 22: 25347159162241162461433882565136
  97. 23: 34589996454813135961785697637136
  98. 24: 2858541763747552538199941619545257144336
  99. 25: 214785886789716796533667464535274377236736
  100. 26: 233292528132679183463629157143235636286736
  101. 27: 244671849793441155421899813243325528686736
  102. 28: 271571567929448516411695557685613529966736
  103. 29: 322388381596588665613523969581347191316736
  104. 30: 385414415625146742626881165526237149942336
  105. 31: 494827714874767379344736911473964125592336
  106. 32: 729191918879671448289782722539515523333136
  107. 33: 739265858539339252384919139328667324488336
  108. 34: 451616391374794616993675837721511769881724292768597136