827 Pythagorean Triple Occurrence.sf 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. #!/usr/bin/ruby
  2. # Pythagorean Triple Occurrence
  3. # https://projecteuler.net/problem=827
  4. # For a given number n, the number of Pythagorean triples in which the number n occurs, is equivalent with:
  5. # (number of solutions to x^2 - y^2 = n^2, with x,y > 0) + (number of solutions to x^2 + y^2 = n^2, with x,y > 0).
  6. # In Sidef, this is:
  7. # (diff_of_squares(n**2).len - 1) + (sum_of_squares(n**2).len - 1)
  8. func count_of_pythagorean_triples(n) {
  9. # Translation of the PARI/GP program by Michel Marcus, Mar 07 2016.
  10. # https://oeis.org/A046081
  11. var n0_sigma0 = 1
  12. var n1_sigma0 = 1
  13. for p,e in (n.factor_exp) {
  14. if (p == 2) {
  15. n0_sigma0 *= (2*e - 1)
  16. }
  17. else {
  18. n0_sigma0 *= (2*e + 1)
  19. if (p % 4 == 1) {
  20. n1_sigma0 *= (2*e + 1)
  21. }
  22. }
  23. }
  24. (n0_sigma0 + n1_sigma0)/2 - 1
  25. }
  26. func smallest_number_with_n_divisors(threshold, upperbound = false, least_solution = Inf, k = 1, max_a = Inf, solutions = 1, n = 1) {
  27. if (solutions == threshold) {
  28. return n
  29. }
  30. if (solutions > threshold) {
  31. return least_solution
  32. }
  33. var p = k.prime
  34. for a in (1 .. max_a) {
  35. n *= p
  36. break if (n > least_solution)
  37. var new_solutions = count_of_pythagorean_triples(n)
  38. if (new_solutions <= threshold) {
  39. least_solution = __FUNC__(threshold, upperbound, least_solution, k+1, (upperbound ? a : Inf), new_solutions, n)
  40. }
  41. }
  42. return least_solution
  43. }
  44. func p827(n) {
  45. var sum = 0
  46. for k in (1..n) {
  47. say "Computing upper-bound for k = #{k}"
  48. var upperbound = smallest_number_with_n_divisors(10**k, true)
  49. say "Upper-bound: #{upperbound}"
  50. var value = smallest_number_with_n_divisors(10**k, false, upperbound)
  51. say "Exact value: #{value}\n"
  52. sum += value
  53. }
  54. return sum
  55. }
  56. say count_of_pythagorean_triples(48)
  57. say count_of_pythagorean_triples(8064000)
  58. assert_eq(
  59. 1000.of(count_of_pythagorean_triples).slice(1),
  60. 1000.of { .sqr.sum_of_squares.len.dec + .sqr.diff_of_squares.len.dec }.slice(1)
  61. )
  62. say p827(18)