Skip to content

Commit

Permalink
Added haskell solutions for the first five problems. Baby steps...
Browse files Browse the repository at this point in the history
  • Loading branch information
Emil Hernvall committed Oct 11, 2011
1 parent 0c2adc4 commit aa12d40
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 60 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
*.o
*.hi
20 changes: 2 additions & 18 deletions 1.hs
@@ -1,20 +1,4 @@
-- Project Euler, Problem 1
-- Emil Hernvall, 2011-03-01

a = 3
b = 5
n_max = 1000

uppervalue max n = fromIntegral (ceiling (max / n) - 1)

n_1 = uppervalue n_max a
n_2 = uppervalue n_max b
n_3 = uppervalue n_max (a*b)

sumofrange c n = c*n*(n+1)/2

totalsum = (sumofrange a n_1) + (sumofrange b n_2) - (sumofrange (a*b) n_3)
answer = sum [ x | x <- [1..999], x `mod` 3 == 0 || x `mod` 5 == 0 ]

main = do
print totalsum

putStrLn (show answer)
19 changes: 9 additions & 10 deletions 2.hs
@@ -1,14 +1,13 @@
c = ((sqrt(5)+1)/2)^3
fib n = fibhelper 1 1 n
where fibhelper a b n
| b < n =
let c = a + b
in [c] ++ (fibhelper b c (n-1))
| otherwise = []

evenfibonacci :: [Integer] -> Integer -> [Integer]
evenfibonacci (n:ns) m = let next = round (c*(fromIntegral n))
in if next < m then evenfibonacci (next:n:ns) m
else n:ns
evenfibonacci [] m = evenfibonacci [2] m
evenfibsum n = sum (filter even (fib n))

total = evenfibonacci [] 4000000
maxfib = 4000000

main = do
print c
print total
print (sum total)
putStrLn (show (evenfibsum maxfib))
40 changes: 23 additions & 17 deletions 3.hs
@@ -1,21 +1,27 @@
n = 600851475143
factorize :: Integer -> [Integer]
factorize n =
let
findfactor n m b
| m <= b && n `mod` m == 0 = [m] ++ (findfactor n (m+1) b) ++ [n `div` m]
| m <= b = findfactor n (m+1) b
| otherwise = []
root = ceiling (sqrt (fromIntegral n))
in findfactor n 2 root

factor :: Integer -> [Integer]
factor x = let searchUntil = (truncate (sqrt (fromIntegral x)))
in filter (\y -> x `mod` y == 0) [2..searchUntil]
primefactorize :: Integer -> [Integer]
primefactorize n =
let
factors = factorize n
isdividable l n = foldr (&&) True [ n `mod` x /= 0 | x <- l, x /= n ]
in [ x | x <- factors, isdividable factors x ]

primefactor2 :: [Integer] -> [Integer] -> [Integer]
primefactor2 x (y:ys) = let rem = (filter (\s -> y `mod` s == 0) x)
next = (primefactor2 (y:x) ys)
in if (length rem) == 0 then [y] ++ next
else next
primefactor2 x [] = []

primefactor :: Integer -> [Integer]
primefactor n = primefactor2 [] (factor n)

factors = primefactor n
maxfactor = last factors
findmax :: [Integer] -> Integer
findmax x =
let
maxfilter a b
| a > b = a
| otherwise = b
in foldr maxfilter 0 x

main = do
print maxfactor
putStrLn (show (findmax (primefactorize 600851475143)))
41 changes: 26 additions & 15 deletions 4.hs
@@ -1,19 +1,30 @@
digitcount :: Integer -> Integer
digitcount n = ceiling (log (fromIntegral n)/(log 10))
factorize :: Int -> [Int]
factorize n =
let
findfactor n m b
| m <= b && n `mod` m == 0 = [m] ++ (findfactor n (m+1) b) ++ [n `div` m]
| m <= b = findfactor n (m+1) b
| otherwise = []
root = ceiling (sqrt (fromIntegral n))
in findfactor n 2 root

palindromize2 :: Integer -> Integer -> Integer
palindromize2 n m | m > 0 = let a = m `div` 10
b = m - a * 10
in palindromize2 (n*10+b) a
| otherwise = n
palindrome :: Int -> Int
palindrome n = let
palindrome' n m c
| n > 0 = palindrome' a b (c+1)
| otherwise = (m,c)
where
a = n `div` 10
b = 10*m + (n `mod` 10)
revnum = palindrome' n 0 0
in n * 10^(snd revnum) + (fst revnum)

palindromize :: Integer -> Integer
palindromize n = palindromize2 n n

palindromseries :: Integer -> Integer -> [Integer]
palindromseries n m = map palindromize [n..m]

test = palindromseries 100 999
largefactors n =
let
factors = factorize n
filtered = filter (\x -> x >= 100 && x <= 999) factors
filtered2 = filter (\x -> (n `div` x) >= 100 && (n `div` x) <= 999) filtered
in (n, filtered2)

main = do
print test
print $ fst . last $ filter (\x -> (snd x) /= []) $ map (largefactors . palindrome) [100..999]
68 changes: 68 additions & 0 deletions 5.hs
@@ -0,0 +1,68 @@
-- find _all_ factors of a number
factorize :: Int -> [Int]
factorize n =
let
findfactor n m b
| m <= b && n `mod` m == 0 = [m] ++ (findfactor n (m+1) b) ++ [n `div` m]
| m <= b = findfactor n (m+1) b
| otherwise = []
root = round (sqrt (fromIntegral n))
factors = findfactor n 2 root
in if factors == [] then [n] else factors

-- eliminate factors that aren't prime by trying to divide them by the other
-- divisors in the list
primefactorize :: Int -> [Int]
primefactorize n =
let
factors = factorize n
isdividable l n = foldr (&&) True [ n `mod` x /= 0 | x <- l, x /= n ]
in [ x | x <- factors, isdividable factors x ]

-- remove duplicate factors
summarize :: [Int] -> [Int]
summarize l =
let
summarize' (l:ls) res
| l `elem` res = summarize' ls res
| otherwise = summarize' ls (l:res)
summarize' [] res = res
in summarize' l []

-- find the exponent of each factor
countfactors :: Int -> [(Int, Int)]
countfactors n =
let
factors = summarize (primefactorize n)

factorexp n m
| n `mod` m == 0 = 1 + (factorexp (n `div` m) m)
| otherwise = 0

iteratefactors (f:fl) = [(f, factorexp n f)] ++ (iteratefactors fl)
iteratefactors [] = []
in iteratefactors factors

-- reduce a list of factors to only contain one entry per base and the maximum exponent
-- in the list.
maxexp :: [(Int, Int)] -> [(Int, Int)]
maxexp factors =
let
maxexp' (u:ul) n m
| (fst u) == n && (snd u) > m = maxexp' ul n (snd u)
| otherwise = maxexp' ul n m
maxexp' [] n m = m

uniquefactors (u:ul) res
| c `elem` res = uniquefactors ul res
| otherwise = uniquefactors ul (c:res)
where c = fst u
uniquefactors [] res = res

newfactors = uniquefactors factors []
in map (\x -> (x, (maxexp' factors x 0))) newfactors

finalproduct l = product $ map (\x -> (fst x) ^ (snd x)) l

main = do
print $ finalproduct $ maxexp $ concat $ map countfactors [2..20]

0 comments on commit aa12d40

Please sign in to comment.