Difference between revisions of "Euler problems/21 to 30"
Line 96: | Line 96: | ||
Solution: |
Solution: |
||
<haskell> |
<haskell> |
||
+ | next n d = (n `mod` d):next (10*n`mod`d) d |
||
+ | |||
+ | idigs n = tail $ take (1+n) $ next 1 n |
||
+ | |||
+ | pos x = map fst . filter ((==x) . snd) . zip [1..] |
||
+ | |||
+ | periods n = let d = idigs n in pos (head d) (tail d) |
||
+ | |||
problem_26 = |
problem_26 = |
||
+ | snd$maximum [(m,a)| |
||
− | fst $ maximumBy (\a b -> snd a `compare` snd b) |
||
+ | a<-[800..1000] , |
||
− | [(n,recurringCycle n) | n <- [1..999]] |
||
+ | let k=periods a, |
||
− | where |
||
+ | not$null k, |
||
− | recurringCycle d = remainders d 10 [] |
||
− | + | let m=head k |
|
+ | ] |
||
− | remainders d r rs = let r' = r `mod` d |
||
− | in case findIndex (== r') rs of |
||
− | Just i -> i + 1 |
||
− | Nothing -> remainders d (10*r') (r':rs) |
||
</haskell> |
</haskell> |
||
Line 112: | Line 117: | ||
Solution: |
Solution: |
||
− | |||
− | The following is written in [http://haskell.org/haskellwiki/Literate_programming#Haskell_and_literate_programming literate Haskell]: |
||
<haskell> |
<haskell> |
||
+ | eulerCoefficients n |
||
− | > import Data.List |
||
+ | = [((len, a*b), (a, b)) |
||
− | |||
+ | | b <- takeWhile (<n) primes, a <- [-b+1..n-1], |
||
− | To be sure we get the maximum type checking of the compiler, |
||
+ | let len = length $ takeWhile (isPrime . (\x -> x^2 + a*x + b)) [0..], |
||
− | we switch off the default type |
||
+ | if b == 2 then even a else odd a, len > 39] |
||
− | |||
+ | |||
− | > default () |
||
+ | problem_27 = snd . fst . maximum . eulerCoefficients $ 1000 |
||
− | |||
− | Generate a list of primes. |
||
− | It works by filtering out numbers that are |
||
− | divisable by a previously found prime |
||
− | |||
− | > primes :: [Int] |
||
− | > primes = sieve (2 : [3, 5..]) |
||
− | > where |
||
− | > sieve (p:xs) = p : sieve (filter (\x -> x `mod` p > 0) xs) |
||
− | |||
− | > isPrime :: Int -> Bool |
||
− | > isPrime x = x `elem` (takeWhile (<= x) primes) |
||
− | |||
− | |||
− | The lists of values we are going to try for a and b; |
||
− | b must be a prime, as n² + an + b is equal to b when n = 0 |
||
− | |||
− | > testRangeA :: [Int] |
||
− | > testRangeA = [-1000 .. 1000] |
||
− | |||
− | > testRangeB :: [Int] |
||
− | > testRangeB = takeWhile (< 1000) primes |
||
− | |||
− | |||
− | The search |
||
− | |||
− | > bestCoefficients :: (Int, Int, Int) |
||
− | > bestCoefficients = |
||
− | > maximumBy (\(x, _, _) (y, _, _) -> compare x y) $ |
||
− | > [f a b | a <- testRangeA, b <- testRangeB] |
||
− | > where |
||
− | |||
− | Generate a list of results of the quadratic formula |
||
− | (only the contiguous primes) |
||
− | wrap the result in a triple, together with a and b |
||
− | |||
− | > f :: Int -> Int -> (Int, Int, Int) |
||
− | > f a b = ( length $ contiguousPrimes a b |
||
− | > , a |
||
− | > , b |
||
− | > ) |
||
− | |||
− | > contiguousPrimes :: Int -> Int -> [Int] |
||
− | > contiguousPrimes a b = takeWhile isPrime (map (quadratic a b) [0..]) |
||
− | |||
− | |||
− | The quadratic formula |
||
− | |||
− | > quadratic :: Int -> Int -> Int -> Int |
||
− | > quadratic a b n = n * n + a * n + b |
||
− | |||
− | |||
− | > problem_27 = |
||
− | > do |
||
− | > let (l, a, b) = bestCoefficients |
||
− | > |
||
− | > putStrLn $ "" |
||
− | > putStrLn $ "Problem Euler 27" |
||
− | > putStrLn $ "" |
||
− | > putStrLn $ "The best quadratic formula found is:" |
||
− | > putStrLn $ " n * n + " ++ show a ++ " * n + " ++ show b |
||
− | > putStrLn $ "" |
||
− | > putStrLn $ "The number of primes is: " ++ (show l) |
||
− | > putStrLn $ "" |
||
− | > putStrLn $ "The primes are:" |
||
− | > print $ take l $ contiguousPrimes a b |
||
− | > putStrLn $ "" |
||
− | |||
− | |||
</haskell> |
</haskell> |
||
Line 197: | Line 132: | ||
Solution: |
Solution: |
||
<haskell> |
<haskell> |
||
+ | problem_28 = sum (map (\n -> 4*(n-2)^2+10*(n-1)) [3,5..1001]) + 1 |
||
− | corners :: Int -> (Int, Int, Int, Int) |
||
− | corners i = (n*n, 1+(n*(2*m)), 2+(n*(2*m-1)), 3+(n*(2*m-2))) |
||
− | where m = (i-1) `div` 2 |
||
− | n = 2*m+1 |
||
− | |||
− | sumcorners :: Int -> Int |
||
− | sumcorners i = a+b+c+d where (a, b, c, d) = corners i |
||
− | |||
− | sumdiags :: Int -> Int |
||
− | sumdiags i | even i = error "not a spiral" |
||
− | | i == 3 = s + 1 |
||
− | | otherwise = s + sumdiags (i-2) |
||
− | where s = sumcorners i |
||
− | |||
− | problem_28 = sumdiags 1001 |
||
</haskell> |
</haskell> |
||
− | |||
− | You can note that from 1 to 3 there's (+2), and such too for 5, 7 and 9, it then goes up to (+4) 4 times, and so on, adding 2 to the number to add for each level of the spiral. You can so avoid all need for multiplications and just do additions with the following code : |
||
− | <haskell>problem_28 = sum . scanl (+) 1 . concatMap (replicate 4) $ [2,4..1000]</haskell> |
||
== [http://projecteuler.net/index.php?section=view&id=29 Problem 29] == |
== [http://projecteuler.net/index.php?section=view&id=29 Problem 29] == |
||
Line 222: | Line 140: | ||
Solution: |
Solution: |
||
<haskell> |
<haskell> |
||
+ | import Control.Monad |
||
− | problem_29 = length . group . sort $ [a^b | a <- [2..100], b <- [2..100]] |
||
+ | problem_29 = length . group . sort $ liftM2 (^) [2..100] [2..100] |
||
</haskell> |
</haskell> |
||
Line 230: | Line 149: | ||
Solution: |
Solution: |
||
<haskell> |
<haskell> |
||
+ | import Data.Array |
||
import Data.Char |
import Data.Char |
||
− | limit = snd $ head $ dropWhile (\(a,b) -> a > b) |
||
− | $ zip (map (9^5*) [1..]) (map (10^) [1..]) |
||
+ | p = listArray (0,9) $ map (^5) [0..9] |
||
− | fifth n = foldr (\a b -> (toInteger(ord a) - 48)^5 + b) 0 $ show n |
||
+ | |||
+ | upperLimit = 295277 |
||
+ | candidates = |
||
− | problem_30 = sum $ filter (\n -> n == fifth n) [2..limit] |
||
+ | [ n | |
||
+ | n <- [10..upperLimit], |
||
+ | (sum $ digits n) `mod` 10 == last(digits n), |
||
+ | powersum n == n |
||
+ | ] |
||
+ | where |
||
+ | digits n = map digitToInt $ show n |
||
+ | powersum n = sum $ map (p!) $ digits n |
||
+ | |||
+ | problem_30 = sum candidates |
||
</haskell> |
</haskell> |
Revision as of 03:46, 22 January 2008
Problem 21
Evaluate the sum of all amicable pairs under 10000.
Solution:
problem_21 =
sum [n |
n <- [2..9999],
let m = eulerTotient n,
m > 1,
m < 10000,
n == eulerTotient m
]
Problem 22
What is the total of all the name scores in the file of first names?
Solution:
import Data.List
import Data.Char
problem_22 = do
input <- readFile "names.txt"
let names = sort $ read$"["++ input++"]"
let scores = zipWith score names [1..]
print $ show $ sum $ scores
where
score w i = (i *) $ sum $ map (\c -> ord c - ord 'A' + 1) w
Problem 23
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
Solution:
import Data.Array
n = 28124
abundant n = eulerTotient n - n > n
abunds_array = listArray (1,n) $ map abundant [1..n]
abunds = filter (abunds_array !) [1..n]
rests x = map (x-) $ takeWhile (<= x `div` 2) abunds
isSum = any (abunds_array !) . rests
problem_23 = putStrLn $ show $ foldl1 (+) $ filter (not . isSum) [1..n]
Problem 24
What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
Solution:
import Data.List
fac 0 = 1
fac n = n * fac (n - 1)
perms [] _= []
perms xs n=
x:( perms ( delete x $ xs ) (mod n m))
where
m=fac$(length(xs) -1)
y=div n m
x = xs!!y
problem_24 = perms "0123456789" 999999
Problem 25
What is the first term in the Fibonacci sequence to contain 1000 digits?
Solution:
import Data.List
fib x
|x==0=0
|x==1=1
|x==2=1
|odd x=(fib (d+1))^2+(fib d)^2
|otherwise=(fib (d+1))^2-(fib (d-1))^2
where
d=div x 2
phi=(1+sqrt 5)/2
dig x=floor( (fromInteger x-1) * log 10 /log phi)
problem_25 =
head[a|a<-[dig num..],(>=limit)$fib a]
where
num=1000
limit=10^(num-1)
Problem 26
Find the value of d < 1000 for which 1/d contains the longest recurring cycle.
Solution:
next n d = (n `mod` d):next (10*n`mod`d) d
idigs n = tail $ take (1+n) $ next 1 n
pos x = map fst . filter ((==x) . snd) . zip [1..]
periods n = let d = idigs n in pos (head d) (tail d)
problem_26 =
snd$maximum [(m,a)|
a<-[800..1000] ,
let k=periods a,
not$null k,
let m=head k
]
Problem 27
Find a quadratic formula that produces the maximum number of primes for consecutive values of n.
Solution:
eulerCoefficients n
= [((len, a*b), (a, b))
| b <- takeWhile (<n) primes, a <- [-b+1..n-1],
let len = length $ takeWhile (isPrime . (\x -> x^2 + a*x + b)) [0..],
if b == 2 then even a else odd a, len > 39]
problem_27 = snd . fst . maximum . eulerCoefficients $ 1000
Problem 28
What is the sum of both diagonals in a 1001 by 1001 spiral?
Solution:
problem_28 = sum (map (\n -> 4*(n-2)^2+10*(n-1)) [3,5..1001]) + 1
Problem 29
How many distinct terms are in the sequence generated by ab for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?
Solution:
import Control.Monad
problem_29 = length . group . sort $ liftM2 (^) [2..100] [2..100]
Problem 30
Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.
Solution:
import Data.Array
import Data.Char
p = listArray (0,9) $ map (^5) [0..9]
upperLimit = 295277
candidates =
[ n |
n <- [10..upperLimit],
(sum $ digits n) `mod` 10 == last(digits n),
powersum n == n
]
where
digits n = map digitToInt $ show n
powersum n = sum $ map (p!) $ digits n
problem_30 = sum candidates