Question
Euler’s Totient function, \varphi(n) [sometimes called the phi function], is used to determine the number of positive numbers less than or equal to n which are relatively prime to n. For example, as 1, 2, 4, 5, 7, and 8, are all less than nine and relatively prime to nine, \varphi(9)=6. The number 1 is considered to be relatively prime to every positive number, so \varphi(1)=1.
Interestingly, \varphi(87109)=79180, and it can be seen that 87109 is a permutation of 79180.
Find the value of n, 1 \lt n \lt 10^7, for which \varphi(n) is a permutation of n and the ratio \frac{n}{\varphi(n)} produces a minimum.
Haskell
import Data.List (sort)
primes :: [Int]
= 2 : sieve primes [3,5..] where
primes :ps) xs = h ++ sieve ps [x | x <- t, rem x p /= 0]
sieve (pwhere (h, t) = span (< p*p) xs
permutation :: Int -> Int -> Bool
= sort (show x) == sort (show y)
permutation x y
totient :: Int -> Int -> Int
= (p1 - 1) * (p2 - 1)
totient p1 p2
candidates :: [(Int, Int)]
= [(n, phi) | p1 <- ps, p2 <- dropWhile (<= p1) ps, let n = p1 * p2, n <= 10000000, let phi = totient p1 p2]
candidates where ps = take 500 primes
main :: IO ()
= print $ snd $ minimum [(fromIntegral n / fromIntegral phi, n) | (n, phi) <- candidates, permutation n phi] main
$ ghc -O2 -o totient-permutation totient-permutation.hs
$ time ./totient-permutation
real 0m0.067s
user 0m0.067s
sys 0m0.000s
Python
#!/usr/bin/env python
from math import sqrt
from operator import mul
from itertools import *
def primes(n):
if n == 2:
return [2]
elif n < 2:
return []
= list(range(3, n+1, 2))
sieve = n ** 0.5
mroot = (n + 1) // 2 - 1
half = 0
i = 3
m while m <= mroot:
if sieve[i]:
= (m * m - 3) // 2
j = 0
sieve[j] while j < half:
= 0
sieve[j] += m
j = i + 1
i = 2 * i + 3
m return [2] + [p for p in sieve if p]
def main():
= combinations(primes(2 * int(sqrt(1e7))), 2)
pairs = (100, 0)
minimum for n, t in ((a * b, (a-1) * (b-1)) for a, b in pairs if a * b < 1e7):
= float(n) / t
ratio if ratio < minimum[0] and sorted(str(n)) == sorted(str(t)):
= (ratio, n)
minimum
print(minimum[1])
if __name__ == "__main__": main()
$ time python3 totient.py
real 0m0.480s
user 0m0.479s
sys 0m0.000s
Ruby
#!/usr/bin/env ruby
require 'mathn'
= [100, 0]
min = (1..(2*Math.sqrt(1e7))).select { |n| n.prime? }
primes .combination(2).select { |a, b| a * b < 1e7 }.each do |a, b|
primes= a * b
n = (a - 1) * (b - 1)
t if n.to_s.split('').sort == t.to_s.split('').sort
if n / t < min[0]
= [n / t, n]
min end
end
end
puts min[1]
$ time ruby totient.rb
real 0m2.918s
user 0m2.902s
sys 0m0.016s