Project Euler - Haskell
Currently I have completed 75 Project Euler problems in Java so I decided to give it a go in Haskell. With the help of tutorials and good ol' fashion trial and error here are the first 10 problems.
This project's GitHub page can be found here
1. Multiples of 3 and 5
import Euler
main = print (sum (filter (divisible [3,5]) [1..999]))
2. Even Fibonacci numbers
import Euler
main = print (sum (filter even (fibm 4000000)))
3. Largest prime factor
import Euler
main = print (last [x | x <- factors 600851475143, isPrime x])
4. Largest palindrome product
import Euler
main = print (maximum
[z | y<-[1..999], x<-[y..999],
let z = x * y,
let r = reversei z, r == z])
5. Smallest multiple
import Euler
{--
full range: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
optimize array:
if n % 20 == 0, then n % 10 == 0 and n % 5 == 0 and n % 2 == 0,
therefore cut out 10, 5, and 2
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
--}
divides1to10 :: Int -> Bool
divides1to10 n = let list = [11..20]
in all (\i -> (mod n i) == 0) list
divideLoop :: Int -> Int
divideLoop n | divides1to10 n = n
| otherwise = divideLoop (n + 1)
main = print (divideLoop 2520)
6. Sum square difference
import Euler
sumOfSquares :: Int -> Int
sumOfSquares n = sum (map (\i -> i^2) [1..n])
squareOfSums :: Int -> Int
squareOfSums n = (sum [1..n])^2
diff :: Int -> Int
diff n = (squareOfSums n) - (sumOfSquares n)
main = print (diff 100)
7. 10001st prime
import Euler
nthPrime :: Int -> Int -> Int
nthPrime n k | k == 10001 = n - 1
| isPrime n = nthPrime (n + 1) (k + 1)
| otherwise = nthPrime (n + 1) k
main = print (nthPrime 1 0)
8. Largest product in a series
import Euler
import Data.Char (digitToInt)
import Data.List (tails)
s = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"
main = do
let n = map digitToInt s
print (maximum (map product [x | x <- map (take 5) (tails n), length x == 5]))
9. Special Pythagorean triplet
import Euler
triplets limit = [ a * b * c
| c <- [1..limit]
, b <- [1..(c-1)]
, a <- [1..(b-1)]
, a + b + c == limit
, a^2 + b^2 == c^2]
main = print (head (triplets 1000))
10. Summation of primes
import Euler
main = print (sum (primeSieve 2000000))
Euler.hs
This is where I place common functions that may be used in other Project Euler Problems
module Euler
(divisible
,fib
,fibs
,fibm
,isPrime
,factors
,reversei
,toDigits
,fromDigits
,primeSieve
,minusl
)
where
import Data.Bits
-- divisible()
divisible :: [Int] -> Int -> Bool
divisible divisors n = any (\divisor -> (mod n divisor) == 0) divisors
-- fib() - fibonacci sequence, generate n-th term
fib :: Int -> Integer
fib = (map fib [0 ..] !!)
where fib 0 = 1
fib 1 = 1
fib n = fib (n-2) + fib (n-1)
-- fibs() - fibonacci sequence, generate n terms
fibs :: Int -> [Integer]
fibs terms = [a | (a,b) <- take
terms
(iterate
(\(a,b) -> (b, a+b))
(0,1))]
-- fibm() - fibonacci sequence max terms, generate terms up to max term
fibm :: Int -> [Integer]
fibm max = [a | (a,b) <- takeWhile
(\(a,b) -> a <= fromIntegral(max))
(iterate
(\(a,b) -> (b, a+b))
(0,1))]
-- isPrime()
isPrime :: Int -> Bool
isPrime n | n <= 1 = False
| otherwise = let root = sqrt (fromIntegral n)
in not (any
(\i -> (mod n i) == 0)
[2..truncate(root)])
-- primeSieve() - Sieve of Eratosthense
-- works but needs to go from 1 to root(n), not root(n) to 2
primeSieveSlow :: Int -> [Int]
primeSieveSlow n = let upper = truncate (sqrt (fromIntegral n))
in siever ([2] ++ [3,5..n]) upper
where siever set 1 = []
siever set 2 = set
siever set n | isPrime (head set) = siever (filterMultiples set n) (n - 1)
| otherwise = filterMultiples set n
where filterMultiples set n = filter (\x -> x == n || (mod x n) /= 0) set
primeSieve m = 2 : sieve [3,5..m]
where sieve [] = []
sieve (p:xs) = p : sieve (minusl xs [p * p, p * p + 2 * p.. m])
-- factors()
factors :: Int -> [Int]
factors n = [x | x <- [2..s], (mod n x) == 0]
where s = floor (sqrt (fromIntegral n))
-- toDigits()
toDigits :: Int -> [Int]
toDigits 0 = []
toDigits x = toDigits (div x 10) ++ [mod x 10]
-- fromDigits()
fromDigits = foldl addDigit 0
where addDigit num d = 10 * num + d
-- reversei()
reversei :: Int -> Int
reversei n = fromDigits (reverse (toDigits n))
-- listSubtract
minusl :: Ord a => [a] -> [a] -> [a]
minusl [] _ = []
minusl xs [] = xs
minusl l1@(x:xs) l2@(y:ys)
| x > y = minusl l1 ys
| x < y = x : minusl xs l2
| otherwise = minusl xs l2