euler/old-haskell/060.hs
2019-06-11 13:43:20 +02:00

70 lines
2.4 KiB
Haskell

-- Problem 60
-- 02 January 2004
--
-- The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property.
--
-- Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.
--
import Prime
numOfDigits x
| x < 10 = 1
| x < 100 = 2
| x < 1000 = 3
| x < 10000 = 4
| x < 100000 = 5
| x < 1000000 = 6
| x < 10000000 = 7
-- | otherwise = truncate (logBase 10 x)
-- equivalent but faster than "read (show x ++ show y)"
concatNumbers :: Int -> Int -> Int
concatNumbers x y = (10^numOfDigits y)*x + y
areConcatPrime :: [Int] -> Bool
areConcatPrime [] = True
areConcatPrime (x:xs) =
-- (areConcatPrime xs) && (and $ map concatPrime_x xs)
all concatPrime_x xs
where
concatPrime_x :: Int -> Bool
concatPrime_x y = all is_prime [concatNumbers x y, concatNumbers y x]
-- for 1 should return a list of one element list containing a unique prime
--
cprimes :: Int -> [[Int]]
cprimes n = concatMap (memoizedConcatPrimes n) [(n-1)..]
-- concatPrimes' :: Int -> Int -> [[Int]]
-- concatPrimes' 0 _ = [[]]
-- concatPrimes' _ (-1) = error "concatPrimes' ERROR"
-- concatPrimes' _ 0 = []
-- concatPrimes' 1 max = [[ primes !! fromInt max ]]
-- concatPrimes' n max = filter areConcatPrime [ p:cprimes | cprimes <- subsets ]
-- where p = primes !! fromInt max
-- -- subsets = memoized !! fromInt (n-1)
-- subsets = concatMap (concatPrimes' (n-1)) [0..(max-1)]
memoizedConcatPrimes n max =
let p = primes !! max
subsets = concatMap (memoizedConcatPrimes (n-1)) [0..(max-1)]
concatPrimes 0 _ = [[]]
concatPrimes _ 0 = []
concatPrimes 1 max = [[ primes !! max ]]
concatPrimes n max = filter areConcatPrime [p:cprimes | cprimes <- subsets ]
in map (map concatPrimes [0..] !! n) [0..] !! max
main = do
print $ take 20 $ cprimes 2
print $ cprimes 3 !! 0
print $ cprimes 3 !! 1
print $ cprimes 3 !! 2
print $ take 20 $ cprimes 3
print $ cprimes 4 !! 0
print $ cprimes 4 !! 1
print $ cprimes 4 !! 2
let res = take 3 $ cprimes 5
print res
print (map sum res)