modular_hyperoperation.jl 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. #!/usr/bin/julia
  2. # Trizen
  3. # Date: 27 August 2016
  4. # https://github.com/trizen
  5. # Generalized implementation of Knuth's up-arrow hyperoperation (modulo some n).
  6. # See also:
  7. # https://en.wikipedia.org/wiki/Knuth%27s_up-arrow_notation
  8. using Memoize
  9. using Printf
  10. const modulo = 10^3
  11. @memoize function hyper1(n::Int64, k::Int64)
  12. powermod(n, k, modulo)
  13. end
  14. @memoize function hyper2(n::Int64, k::Int64)
  15. k <= 1 && return n
  16. hyper1(n, hyper2(n, k - 1))
  17. end
  18. @memoize function hyper3(n::Int64, k::Int64)
  19. k <= 1 && return n
  20. hyper2(n, hyper3(n, k - 1))
  21. end
  22. @memoize function hyper4(n::Int64, k::Int64)
  23. k <= 1 && return n
  24. hyper3(n, hyper4(n, k - 1))
  25. end
  26. @memoize function knuth(k::Int64, n::Int64, g::Int64)
  27. k %= modulo
  28. g %= modulo
  29. n >= 1 && g == 0 && return 1
  30. n == 0 && return ((k * g) % modulo)
  31. n == 1 && return (hyper1(k, g))
  32. n == 2 && return (hyper2(k, g))
  33. n == 3 && return (hyper3(k, g))
  34. n == 4 && return (hyper4(k, g))
  35. knuth(k, n - 1, knuth(k, n, g - 1))
  36. end
  37. for i in 0:6
  38. x = 1 + trunc(Int64, rand()*100)
  39. y = 1 + trunc(Int64, rand()*100)
  40. n = knuth(x, i, y)
  41. @printf("%5s %10s %5s = %5s (mod %s)\n", x, repeat("^", i), y, n, modulo)
  42. end