nth_prime_power.sf 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #!/usr/bin/ruby
  2. # Daniel "Trizen" Șuteu
  3. # Date: 07 July 2022
  4. # https://github.com/trizen
  5. # Compute the n-th prime power, using binary search and the prime-power counting function.
  6. # See also:
  7. # https://oeis.org/A143039
  8. func prime_power_count_lower(n) {
  9. sum(1..n.ilog2, {|k|
  10. prime_count_lower(n.iroot(k))
  11. })
  12. }
  13. func prime_power_count_upper(n) {
  14. sum(1..n.ilog2, {|k|
  15. prime_count_upper(n.iroot(k))
  16. })
  17. }
  18. func nth_prime_power_lower(n) {
  19. bsearch_min(n, n.nth_prime_upper, {|k|
  20. prime_power_count_upper(k) <=> n
  21. })
  22. }
  23. func nth_prime_power_upper(n) {
  24. bsearch_max(n, n.nth_prime_upper, {|k|
  25. prime_power_count_lower(k) <=> n
  26. })
  27. }
  28. func nth_prime_power(n) {
  29. n == 0 && return 1 # not a prime power, but...
  30. n <= 0 && return NaN
  31. n == 1 && return 2
  32. var min = nth_prime_power_lower(n)
  33. var max = nth_prime_power_upper(n)
  34. var k = 0
  35. var c = 0
  36. loop {
  37. k = (min + max)>>1
  38. c = prime_power_count(k)
  39. if (abs(c - n) <= n.iroot(3)) {
  40. break
  41. }
  42. given (c <=> n) {
  43. when (+1) { max = k-1 }
  44. when (-1) { min = k+1 }
  45. else { break }
  46. }
  47. }
  48. while (!k.is_prime_power) {
  49. --k
  50. }
  51. while (c != n) {
  52. var j = (n <=> c)
  53. k += j
  54. c += j
  55. k += j while !k.is_prime_power
  56. }
  57. return k
  58. }
  59. for n in (1..10) {
  60. var pp = nth_prime_power(10**n)
  61. assert(pp.is_prime_power)
  62. assert_eq(pp.prime_power_count, 10**n)
  63. assert_eq(10**n -> nth_prime_power, pp)
  64. say "PP(10^#{n}) = #{pp}"
  65. }
  66. assert_eq(
  67. nth_prime_power.map(1..100),
  68. 100.by { .is_prime_power }
  69. )
  70. __END__
  71. PP(10^1) = 16
  72. PP(10^2) = 419
  73. PP(10^3) = 7517
  74. PP(10^4) = 103511
  75. PP(10^5) = 1295953
  76. PP(10^6) = 15474787
  77. PP(10^7) = 179390821
  78. PP(10^8) = 2037968761
  79. PP(10^9) = 22801415981
  80. PP(10^10) = 252096675073
  81. PP(10^11) = 2760723662941
  82. PP(10^12) = 29996212395727
  83. PP(10^13) = 323780470283789
  84. PP(10^14) = 3475385632514321
  85. PP(10^15) = 37124507635789309