legendre_prime_counting_function.sf 1001 B

1234567891011121314151617181920212223242526272829303132333435
  1. #!/usr/bin/ruby
  2. # The Legendre phi function is defined recursively as:
  3. # φ(x, 0) = x
  4. # φ(x, a) = φ(x, a−1) − φ(floor(x/p_a), a−1), where p_a is the a-th prime number.
  5. # From which the prime counting function, π(n), can be defined as:
  6. # π(n) = 0 when n < 2
  7. # π(n) = φ(n, a) + a - 1, where a = π(√n), n ≥ 2
  8. # See also:
  9. # https://rosettacode.org/wiki/Legendre_prime_counting_function
  10. func legendre_phi(x, a) is cached {
  11. return x if (a <= 0)
  12. var p = a.prime
  13. return __FUNC__(x, a-1) if (p > x)
  14. __FUNC__(x, a-1) - __FUNC__(idiv(x, p), a-1)
  15. }
  16. func legendre_prime_count(n) is cached {
  17. return 0 if (n < 2)
  18. var a = __FUNC__(n.isqrt)
  19. legendre_phi(n, a) + a - 1
  20. }
  21. print("e n Legendre builtin\n",
  22. "- - -------- -------\n")
  23. for n in (1 .. 5) {
  24. printf("%d %12d %10d %10d\n", n, 10**n,
  25. legendre_prime_count(10**n), prime_count(10**n))
  26. assert_eq(legendre_prime_count(10**n), prime_count(10**n))
  27. }