Make stack project for Haskell

This commit is contained in:
2024-12-15 19:44:51 +01:00
parent 751673989c
commit 71783f4043
41 changed files with 356 additions and 34 deletions

75
Haskell/src/Main.hs Normal file
View File

@ -0,0 +1,75 @@
module Main (main) where
import P001
import P002
import P003
import P004
import P005
import P006
import P007
import P008
import P009
import P010
import P011
import P012
import P013
import P014
import P015
import P016
import P019
import P020
import P021
import P022
import P023
import P024
import P025
import P026
import P027
import P029
import P030
import P034
import P035
import P036
import P041
import P052
import P054
import System.Environment (getArgs)
main :: IO ()
main = do
args <- getArgs
case args of
"1" : _ -> p001
"2" : _ -> p002
"3" : _ -> p003
"4" : _ -> p004
"5" : _ -> p005
"6" : _ -> p006
"7" : _ -> p007
"8" : _ -> p008
"9" : _ -> p009
"10" : _ -> p010
"11" : _ -> p011
"12" : _ -> p012
"13" : _ -> p013
"14" : _ -> p014
"15" : _ -> p015
"16" : _ -> p016
"19" : _ -> p019
"20" : _ -> p020
"21" : _ -> p021
"22" : _ -> p022
"23" : _ -> p023
"24" : _ -> p024
"25" : _ -> p025
"26" : _ -> p026
"27" : _ -> p027
"29" : _ -> p029
"30" : _ -> p030
"34" : _ -> p034
"35" : _ -> p035
"36" : _ -> p036
"41" : _ -> p041
"52" : _ -> p052
"54" : _ -> p054
_ -> error "Not implemented"

18
Haskell/src/P001.hs Normal file
View File

@ -0,0 +1,18 @@
-- If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
--
-- Find the sum of all the multiples of 3 or 5 below 1000.
module P001 (p001) where
sumMultiples :: Int
sumMultiples = sum $ filter p [1 .. 999]
where
p n = n `mod` 3 == 0 || n `mod` 5 == 0
p001 :: IO ()
p001 = do
let result = sumMultiples
putStrLn $
"Project Euler, Problem 1\n"
++ "Answer: "
++ show result

23
Haskell/src/P002.hs Normal file
View File

@ -0,0 +1,23 @@
-- Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
--
-- 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
--
-- By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
module P002 (p002) where
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
sumEvenFib :: Int
sumEvenFib = sum $ filter even $ takeWhile (<= 4000000) (map fib [0 ..])
p002 :: IO ()
p002 = do
let result = sumEvenFib
putStrLn $
"Project Euler, Problem 2\n"
++ "Answer: "
++ show result

20
Haskell/src/P003.hs Normal file
View File

@ -0,0 +1,20 @@
-- The prime factors of 13195 are 5, 7, 13 and 29. --
-- What is the largest prime factor of the number 600851475143?
module P003 (p003) where
import ProjectEuler (isPrime)
maxPrimeFactor :: Int -> Int
maxPrimeFactor n
| isPrime n = n
| even n = maxPrimeFactor $ n `div` 2
| otherwise = maxPrimeFactor $ n `div` head [i | i <- [3, 5 ..], n `mod` i == 0 && isPrime i]
p003 :: IO ()
p003 = do
let result = maxPrimeFactor 600851475143
putStrLn $
"Project Euler, Problem 3\n"
++ "Answer: "
++ show result

20
Haskell/src/P004.hs Normal file
View File

@ -0,0 +1,20 @@
-- A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
--
-- Find the largest palindrome made from the product of two 3-digit numbers.
module P004 (p004) where
isPalindrome :: Int -> Bool
isPalindrome n = show n == reverse (show n)
maxPalindrome :: Int
maxPalindrome =
maximum . filter isPalindrome $ (*) <$> [100 .. 999] <*> [100 .. 999]
p004 :: IO ()
p004 = do
let result = maxPalindrome
putStrLn $
"Project Euler, Problem 4\n"
++ "Answer: "
++ show result

15
Haskell/src/P005.hs Normal file
View File

@ -0,0 +1,15 @@
-- 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
--
-- What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
module P005 (p005) where
import ProjectEuler (lcmm)
p005 :: IO ()
p005 = do
let result = lcmm [1 .. 20]
putStrLn $
"Project Euler, Problem 5\n"
++ "Answer: "
++ show result

24
Haskell/src/P006.hs Normal file
View File

@ -0,0 +1,24 @@
-- The sum of the squares of the first ten natural numbers is,
--
-- 1^2 + 2^2 + ... + 10^2 = 385
--
-- The square of the sum of the first ten natural numbers is,
--
-- (1 + 2 + ... + 10)^2 = 55^2 = 3025
--
-- Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is 3025 385 = 2640.
--
-- Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
module P006 (p006) where
sumSquareDiff :: Int -> Int
sumSquareDiff n = (sum [1 .. n] ^ 2) - sum (map (^ 2) [1 .. n])
p006 :: IO ()
p006 = do
let result = sumSquareDiff 100
putStrLn $
"Project Euler, Problem 6\n"
++ "Answer: "
++ show result

18
Haskell/src/P007.hs Normal file
View File

@ -0,0 +1,18 @@
-- By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
--
-- What is the 10 001st prime number?
module P007 (p007) where
import ProjectEuler (isPrime)
nthPrime :: Int -> Int
nthPrime n = last $ take n [x | x <- [1 ..], isPrime x]
p007 :: IO ()
p007 = do
let result = nthPrime 10001
putStrLn $
"Project Euler, Problem 7\n"
++ "Answer: "
++ show result

62
Haskell/src/P008.hs Normal file
View File

@ -0,0 +1,62 @@
-- The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.
--
-- 73167176531330624919225119674426574742355349194934
-- 96983520312774506326239578318016984801869478851843
-- 85861560789112949495459501737958331952853208805511
-- 12540698747158523863050715693290963295227443043557
-- 66896648950445244523161731856403098711121722383113
-- 62229893423380308135336276614282806444486645238749
-- 30358907296290491560440772390713810515859307960866
-- 70172427121883998797908792274921901699720888093776
-- 65727333001053367881220235421809751254540594752243
-- 52584907711670556013604839586446706324415722155397
-- 53697817977846174064955149290862569321978468622482
-- 83972241375657056057490261407972968652414535100474
-- 82166370484403199890008895243450658541227588666881
-- 16427171479924442928230863465674813919123162824586
-- 17866458359124566529476545682848912883142607690042
-- 24219022671055626321111109370544217506941658960408
-- 07198403850962455444362981230987879927244284909188
-- 84580156166097919133875499200524063689912560717606
-- 05886116467109405077541002256983155200055935729725
-- 71636269561882670428252483600823257530420752963450
--
-- Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
module P008 (p008) where
import Data.Char (digitToInt)
nDigitProduct :: Int -> String -> Int
nDigitProduct n s
| length s < n = -1
| otherwise = max (product (map digitToInt (take n s))) (nDigitProduct n (tail s))
p008 :: IO ()
p008 = do
let s =
"73167176531330624919225119674426574742355349194934"
++ "96983520312774506326239578318016984801869478851843"
++ "85861560789112949495459501737958331952853208805511"
++ "12540698747158523863050715693290963295227443043557"
++ "66896648950445244523161731856403098711121722383113"
++ "62229893423380308135336276614282806444486645238749"
++ "30358907296290491560440772390713810515859307960866"
++ "70172427121883998797908792274921901699720888093776"
++ "65727333001053367881220235421809751254540594752243"
++ "52584907711670556013604839586446706324415722155397"
++ "53697817977846174064955149290862569321978468622482"
++ "83972241375657056057490261407972968652414535100474"
++ "82166370484403199890008895243450658541227588666881"
++ "16427171479924442928230863465674813919123162824586"
++ "17866458359124566529476545682848912883142607690042"
++ "24219022671055626321111109370544217506941658960408"
++ "07198403850962455444362981230987879927244284909188"
++ "84580156166097919133875499200524063689912560717606"
++ "05886116467109405077541002256983155200055935729725"
++ "71636269561882670428252483600823257530420752963450"
result = nDigitProduct 13 s
putStrLn $
"Project Euler, Problem 8\n"
++ "Answer: "
++ show result

25
Haskell/src/P009.hs Normal file
View File

@ -0,0 +1,25 @@
-- A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
--
-- a2 + b2 = c2
--
-- For example, 32 + 42 = 9 + 16 = 25 = 52.
--
-- There exists exactly one Pythagorean triplet for which a + b + c = 1000.
--
-- Find the product abc.
module P009 (p009) where
pythagoreanTriplet :: Int -> (Int, Int, Int)
pythagoreanTriplet n = head [(x, y, z) | x <- [1 .. n], y <- [x .. n], z <- [y .. n], x + y + z == n, x ^ 2 + y ^ 2 == z ^ 2]
prodTriplet :: (Int, Int, Int) -> Int
prodTriplet (x, y, z) = x * y * z
p009 :: IO ()
p009 = do
let result = prodTriplet $ pythagoreanTriplet 1000
putStrLn $
"Project Euler, Problem 9\n"
++ "Answer: "
++ show result

15
Haskell/src/P010.hs Normal file
View File

@ -0,0 +1,15 @@
-- The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
--
-- Find the sum of all the primes below two million.
module P010 (p010) where
import ProjectEuler (primeSieve)
p010 :: IO ()
p010 = do
let result = sum $ takeWhile (< 2000000) primeSieve
putStrLn $
"Project Euler, Problem 10\n"
++ "Answer: "
++ show result

75
Haskell/src/P011.hs Normal file
View File

@ -0,0 +1,75 @@
-- In the 20×20 grid below, four numbers along a diagonal line have been marked in red.
--
-- 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
-- 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
-- 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
-- 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
-- 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
-- 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
-- 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
-- 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
-- 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
-- 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
-- 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
-- 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
-- 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
-- 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
-- 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
-- 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
-- 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
-- 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
-- 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
-- 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
--
-- The product of these numbers is 26 × 63 × 78 × 14 = 1788696.
--
-- What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?
module P011 (p011) where
import Data.List (transpose)
diagonals :: [[Int]] -> [[Int]]
diagonals xs = diagonals' xs ++ diagonals' ((transpose . reverse) xs)
where
diagonals' xs =
transpose (zipWith drop [0 ..] xs)
++ transpose (zipWith drop [1 ..] (transpose xs))
maxProd4 :: [Int] -> Int
maxProd4 [x, y, z] = 0
maxProd4 (w : x : y : z : xs) = max (w * x * y * z) (maxProd4 (x : y : z : xs))
p011 :: IO ()
p011 = do
let grid =
[ [8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8],
[49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0],
[81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13, 36, 65],
[52, 70, 95, 23, 4, 60, 11, 42, 69, 24, 68, 56, 1, 32, 56, 71, 37, 2, 36, 91],
[22, 31, 16, 71, 51, 67, 63, 89, 41, 92, 36, 54, 22, 40, 40, 28, 66, 33, 13, 80],
[24, 47, 32, 60, 99, 3, 45, 2, 44, 75, 33, 53, 78, 36, 84, 20, 35, 17, 12, 50],
[32, 98, 81, 28, 64, 23, 67, 10, 26, 38, 40, 67, 59, 54, 70, 66, 18, 38, 64, 70],
[67, 26, 20, 68, 2, 62, 12, 20, 95, 63, 94, 39, 63, 8, 40, 91, 66, 49, 94, 21],
[24, 55, 58, 5, 66, 73, 99, 26, 97, 17, 78, 78, 96, 83, 14, 88, 34, 89, 63, 72],
[21, 36, 23, 9, 75, 0, 76, 44, 20, 45, 35, 14, 0, 61, 33, 97, 34, 31, 33, 95],
[78, 17, 53, 28, 22, 75, 31, 67, 15, 94, 3, 80, 4, 62, 16, 14, 9, 53, 56, 92],
[16, 39, 5, 42, 96, 35, 31, 47, 55, 58, 88, 24, 0, 17, 54, 24, 36, 29, 85, 57],
[86, 56, 0, 48, 35, 71, 89, 7, 5, 44, 44, 37, 44, 60, 21, 58, 51, 54, 17, 58],
[19, 80, 81, 68, 5, 94, 47, 69, 28, 73, 92, 13, 86, 52, 17, 77, 4, 89, 55, 40],
[4, 52, 8, 83, 97, 35, 99, 16, 7, 97, 57, 32, 16, 26, 26, 79, 33, 27, 98, 66],
[88, 36, 68, 87, 57, 62, 20, 72, 3, 46, 33, 67, 46, 55, 12, 32, 63, 93, 53, 69],
[4, 42, 16, 73, 38, 25, 39, 11, 24, 94, 72, 18, 8, 46, 29, 32, 40, 62, 76, 36],
[20, 69, 36, 41, 72, 30, 23, 88, 34, 62, 99, 69, 82, 67, 59, 85, 74, 4, 36, 16],
[20, 73, 35, 29, 78, 31, 90, 1, 74, 31, 49, 71, 48, 86, 81, 16, 23, 57, 5, 54],
[1, 70, 54, 71, 83, 51, 54, 69, 16, 92, 33, 48, 61, 43, 52, 1, 89, 19, 67, 48]
]
diags = filter (\x -> length x >= 4) $ diagonals grid
maxRow = maximum $ map maxProd4 grid
maxCol = maximum . map maxProd4 $ transpose grid
maxDiag = maximum $ map maxProd4 diags
result = maximum [maxRow, maxCol, maxDiag]
putStrLn $
"Project Euler, Problem 11\n"
++ "Answer: "
++ show result

37
Haskell/src/P012.hs Normal file
View File

@ -0,0 +1,37 @@
-- The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28.
-- The first ten terms would be:
--
-- 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
--
-- Let us list the factors of the first seven triangle numbers:
--
-- 1: 1
-- 3: 1,3
-- 6: 1,2,3,6
-- 10: 1,2,5,10
-- 15: 1,3,5,15
-- 21: 1,3,7,21
-- 28: 1,2,4,7,14,28
--
-- We can see that 28 is the first triangle number to have over five divisors.
--
-- What is the value of the first triangle number to have over five hundred divisors?
module P012 (p012) where
import Data.List (nub)
import ProjectEuler (countDivisors)
triangNumbers :: [Int]
triangNumbers = scanl1 (+) [1 ..]
triang500 :: Int
triang500 = head [x | x <- triangNumbers, countDivisors x > 500]
p012 :: IO ()
p012 = do
let result = triang500
putStrLn $
"Project Euler, Problem 12\n"
++ "Answer: "
++ show result

219
Haskell/src/P013.hs Normal file
View File

@ -0,0 +1,219 @@
-- Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.
--
-- 37107287533902102798797998220837590246510135740250
-- 46376937677490009712648124896970078050417018260538
-- 74324986199524741059474233309513058123726617309629
-- 91942213363574161572522430563301811072406154908250
-- 23067588207539346171171980310421047513778063246676
-- 89261670696623633820136378418383684178734361726757
-- 28112879812849979408065481931592621691275889832738
-- 44274228917432520321923589422876796487670272189318
-- 47451445736001306439091167216856844588711603153276
-- 70386486105843025439939619828917593665686757934951
-- 62176457141856560629502157223196586755079324193331
-- 64906352462741904929101432445813822663347944758178
-- 92575867718337217661963751590579239728245598838407
-- 58203565325359399008402633568948830189458628227828
-- 80181199384826282014278194139940567587151170094390
-- 35398664372827112653829987240784473053190104293586
-- 86515506006295864861532075273371959191420517255829
-- 71693888707715466499115593487603532921714970056938
-- 54370070576826684624621495650076471787294438377604
-- 53282654108756828443191190634694037855217779295145
-- 36123272525000296071075082563815656710885258350721
-- 45876576172410976447339110607218265236877223636045
-- 17423706905851860660448207621209813287860733969412
-- 81142660418086830619328460811191061556940512689692
-- 51934325451728388641918047049293215058642563049483
-- 62467221648435076201727918039944693004732956340691
-- 15732444386908125794514089057706229429197107928209
-- 55037687525678773091862540744969844508330393682126
-- 18336384825330154686196124348767681297534375946515
-- 80386287592878490201521685554828717201219257766954
-- 78182833757993103614740356856449095527097864797581
-- 16726320100436897842553539920931837441497806860984
-- 48403098129077791799088218795327364475675590848030
-- 87086987551392711854517078544161852424320693150332
-- 59959406895756536782107074926966537676326235447210
-- 69793950679652694742597709739166693763042633987085
-- 41052684708299085211399427365734116182760315001271
-- 65378607361501080857009149939512557028198746004375
-- 35829035317434717326932123578154982629742552737307
-- 94953759765105305946966067683156574377167401875275
-- 88902802571733229619176668713819931811048770190271
-- 25267680276078003013678680992525463401061632866526
-- 36270218540497705585629946580636237993140746255962
-- 24074486908231174977792365466257246923322810917141
-- 91430288197103288597806669760892938638285025333403
-- 34413065578016127815921815005561868836468420090470
-- 23053081172816430487623791969842487255036638784583
-- 11487696932154902810424020138335124462181441773470
-- 63783299490636259666498587618221225225512486764533
-- 67720186971698544312419572409913959008952310058822
-- 95548255300263520781532296796249481641953868218774
-- 76085327132285723110424803456124867697064507995236
-- 37774242535411291684276865538926205024910326572967
-- 23701913275725675285653248258265463092207058596522
-- 29798860272258331913126375147341994889534765745501
-- 18495701454879288984856827726077713721403798879715
-- 38298203783031473527721580348144513491373226651381
-- 34829543829199918180278916522431027392251122869539
-- 40957953066405232632538044100059654939159879593635
-- 29746152185502371307642255121183693803580388584903
-- 41698116222072977186158236678424689157993532961922
-- 62467957194401269043877107275048102390895523597457
-- 23189706772547915061505504953922979530901129967519
-- 86188088225875314529584099251203829009407770775672
-- 11306739708304724483816533873502340845647058077308
-- 82959174767140363198008187129011875491310547126581
-- 97623331044818386269515456334926366572897563400500
-- 42846280183517070527831839425882145521227251250327
-- 55121603546981200581762165212827652751691296897789
-- 32238195734329339946437501907836945765883352399886
-- 75506164965184775180738168837861091527357929701337
-- 62177842752192623401942399639168044983993173312731
-- 32924185707147349566916674687634660915035914677504
-- 99518671430235219628894890102423325116913619626622
-- 73267460800591547471830798392868535206946944540724
-- 76841822524674417161514036427982273348055556214818
-- 97142617910342598647204516893989422179826088076852
-- 87783646182799346313767754307809363333018982642090
-- 10848802521674670883215120185883543223812876952786
-- 71329612474782464538636993009049310363619763878039
-- 62184073572399794223406235393808339651327408011116
-- 66627891981488087797941876876144230030984490851411
-- 60661826293682836764744779239180335110989069790714
-- 85786944089552990653640447425576083659976645795096
-- 66024396409905389607120198219976047599490197230297
-- 64913982680032973156037120041377903785566085089252
-- 16730939319872750275468906903707539413042652315011
-- 94809377245048795150954100921645863754710598436791
-- 78639167021187492431995700641917969777599028300699
-- 15368713711936614952811305876380278410754449733078
-- 40789923115535562561142322423255033685442488917353
-- 44889911501440648020369068063960672322193204149535
-- 41503128880339536053299340368006977710650566631954
-- 81234880673210146739058568557934581403627822703280
-- 82616570773948327592232845941706525094512325230608
-- 22918802058777319719839450180888072429661980811197
-- 77158542502016545090413245809786882778948721859617
-- 72107838435069186155435662884062257473692284509516
-- 20849603980134001723930671666823555245252804609722
-- 53503534226472524250874054075591789781264330331690
module P013 (p013) where
firstDigitsSum :: Int -> [Integer] -> Int
firstDigitsSum n xs = read . take n . show $ sum xs
p013 :: IO ()
p013 = do
let result =
firstDigitsSum
10
[ 37107287533902102798797998220837590246510135740250,
46376937677490009712648124896970078050417018260538,
74324986199524741059474233309513058123726617309629,
91942213363574161572522430563301811072406154908250,
23067588207539346171171980310421047513778063246676,
89261670696623633820136378418383684178734361726757,
28112879812849979408065481931592621691275889832738,
44274228917432520321923589422876796487670272189318,
47451445736001306439091167216856844588711603153276,
70386486105843025439939619828917593665686757934951,
62176457141856560629502157223196586755079324193331,
64906352462741904929101432445813822663347944758178,
92575867718337217661963751590579239728245598838407,
58203565325359399008402633568948830189458628227828,
80181199384826282014278194139940567587151170094390,
35398664372827112653829987240784473053190104293586,
86515506006295864861532075273371959191420517255829,
71693888707715466499115593487603532921714970056938,
54370070576826684624621495650076471787294438377604,
53282654108756828443191190634694037855217779295145,
36123272525000296071075082563815656710885258350721,
45876576172410976447339110607218265236877223636045,
17423706905851860660448207621209813287860733969412,
81142660418086830619328460811191061556940512689692,
51934325451728388641918047049293215058642563049483,
62467221648435076201727918039944693004732956340691,
15732444386908125794514089057706229429197107928209,
55037687525678773091862540744969844508330393682126,
18336384825330154686196124348767681297534375946515,
80386287592878490201521685554828717201219257766954,
78182833757993103614740356856449095527097864797581,
16726320100436897842553539920931837441497806860984,
48403098129077791799088218795327364475675590848030,
87086987551392711854517078544161852424320693150332,
59959406895756536782107074926966537676326235447210,
69793950679652694742597709739166693763042633987085,
41052684708299085211399427365734116182760315001271,
65378607361501080857009149939512557028198746004375,
35829035317434717326932123578154982629742552737307,
94953759765105305946966067683156574377167401875275,
88902802571733229619176668713819931811048770190271,
25267680276078003013678680992525463401061632866526,
36270218540497705585629946580636237993140746255962,
24074486908231174977792365466257246923322810917141,
91430288197103288597806669760892938638285025333403,
34413065578016127815921815005561868836468420090470,
23053081172816430487623791969842487255036638784583,
11487696932154902810424020138335124462181441773470,
63783299490636259666498587618221225225512486764533,
67720186971698544312419572409913959008952310058822,
95548255300263520781532296796249481641953868218774,
76085327132285723110424803456124867697064507995236,
37774242535411291684276865538926205024910326572967,
23701913275725675285653248258265463092207058596522,
29798860272258331913126375147341994889534765745501,
18495701454879288984856827726077713721403798879715,
38298203783031473527721580348144513491373226651381,
34829543829199918180278916522431027392251122869539,
40957953066405232632538044100059654939159879593635,
29746152185502371307642255121183693803580388584903,
41698116222072977186158236678424689157993532961922,
62467957194401269043877107275048102390895523597457,
23189706772547915061505504953922979530901129967519,
86188088225875314529584099251203829009407770775672,
11306739708304724483816533873502340845647058077308,
82959174767140363198008187129011875491310547126581,
97623331044818386269515456334926366572897563400500,
42846280183517070527831839425882145521227251250327,
55121603546981200581762165212827652751691296897789,
32238195734329339946437501907836945765883352399886,
75506164965184775180738168837861091527357929701337,
62177842752192623401942399639168044983993173312731,
32924185707147349566916674687634660915035914677504,
99518671430235219628894890102423325116913619626622,
73267460800591547471830798392868535206946944540724,
76841822524674417161514036427982273348055556214818,
97142617910342598647204516893989422179826088076852,
87783646182799346313767754307809363333018982642090,
10848802521674670883215120185883543223812876952786,
71329612474782464538636993009049310363619763878039,
62184073572399794223406235393808339651327408011116,
66627891981488087797941876876144230030984490851411,
60661826293682836764744779239180335110989069790714,
85786944089552990653640447425576083659976645795096,
66024396409905389607120198219976047599490197230297,
64913982680032973156037120041377903785566085089252,
16730939319872750275468906903707539413042652315011,
94809377245048795150954100921645863754710598436791,
78639167021187492431995700641917969777599028300699,
15368713711936614952811305876380278410754449733078,
40789923115535562561142322423255033685442488917353,
44889911501440648020369068063960672322193204149535,
41503128880339536053299340368006977710650566631954,
81234880673210146739058568557934581403627822703280,
82616570773948327592232845941706525094512325230608,
22918802058777319719839450180888072429661980811197,
77158542502016545090413245809786882778948721859617,
72107838435069186155435662884062257473692284509516,
20849603980134001723930671666823555245252804609722,
53503534226472524250874054075591789781264330331690
]
putStrLn $
"Project Euler, Problem 13\n"
++ "Answer: "
++ show result

34
Haskell/src/P014.hs Normal file
View File

@ -0,0 +1,34 @@
-- The following iterative sequence is defined for the set of positive integers:
--
-- n → n/2 (n is even)
-- n → 3n + 1 (n is odd)
--
-- Using the rule above and starting with 13, we generate the following sequence:
--
-- 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
--
-- It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem),
-- it is thought that all starting numbers finish at 1.
--
-- Which starting number, under one million, produces the longest chain?
--
-- NOTE: Once the chain starts the terms are allowed to go above one million.
module P014 (p014) where
collatz :: Int -> [Int]
collatz 1 = [1]
collatz n
| even n = n : collatz (n `div` 2)
| odd n = n : collatz (3 * n + 1)
maxCollatzLength :: Int -> Int
maxCollatzLength n = snd $ maximum $ zip [length (collatz x) | x <- [1 .. n - 1]] [1 .. n - 1]
p014 :: IO ()
p014 = do
let result = maxCollatzLength 1000000
putStrLn $
"Project Euler, Problem 14\n"
++ "Answer: "
++ show result

16
Haskell/src/P015.hs Normal file
View File

@ -0,0 +1,16 @@
-- Starting in the top left corner of a 2×2 grid, and only being able to move to the right and down, there are exactly 6 routes to the bottom right corner
-- How many such routes are there through a 20×20 grid?
module P015 (p015) where
factorial :: (Integral a) => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)
p015 :: IO ()
p015 = do
let result = factorial 40 `div` factorial 20 ^ 2
putStrLn $
"Project Euler, Problem 15\n"
++ "Answer: "
++ show result

15
Haskell/src/P016.hs Normal file
View File

@ -0,0 +1,15 @@
-- 2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
--
-- What is the sum of the digits of the number 2^1000?
module P016 (p016) where
import ProjectEuler (digitSum)
p016 :: IO ()
p016 = do
let result = digitSum $ 2 ^ 1000
putStrLn $
"Project Euler, Problem 16\n"
++ "Answer: "
++ show result

31
Haskell/src/P019.hs Normal file
View File

@ -0,0 +1,31 @@
-- You are given the following information, but you may prefer to do some research for yourself.
--
-- 1 Jan 1900 was a Monday.
-- Thirty days has September,
-- April, June and November.
-- All the rest have thirty-one,
-- Saving February alone,
-- Which has twenty-eight, rain or shine.
-- And on leap years, twenty-nine.
-- A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
--
-- How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
module P019 (p019) where
import Data.Time.Calendar (Day, DayOfWeek (Sunday), dayOfWeek, fromGregorian)
countSundaysFirst :: Day -> Day -> Int
countSundaysFirst start end =
let days = [start .. end]
in length $ filter (\x -> dayOfWeek x == Sunday && [last (init (show x)), last (show x)] == "01") days
p019 :: IO ()
p019 = do
let startDate = fromGregorian 1901 1 1
endDate = fromGregorian 2000 12 31
result = countSundaysFirst startDate endDate
putStrLn $
"Project Euler, Problem 19\n"
++ "Answer: "
++ show result

22
Haskell/src/P020.hs Normal file
View File

@ -0,0 +1,22 @@
-- n! means n × (n 1) × ... × 3 × 2 × 1
--
-- For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800,
-- and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.
--
-- Find the sum of the digits in the number 100!
module P020 (p020) where
import ProjectEuler (digitSum)
factorial :: (Integral a) => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)
p020 :: IO ()
p020 = do
let result = digitSum $ factorial 100
putStrLn $
"Project Euler, Problem 20\n"
++ "Answer: "
++ show result

28
Haskell/src/P021.hs Normal file
View File

@ -0,0 +1,28 @@
-- Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n).
-- If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.
--
-- For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284.
-- The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.
--
-- Evaluate the sum of all the amicable numbers under 10000.
module P021 (p021) where
import ProjectEuler (sumProperDivisors)
properDivisors :: (Integral a) => a -> [a]
properDivisors n = [x | x <- [1 .. n - 1], n `mod` x == 0]
amicable :: (Integral a) => a -> a -> Bool
amicable x y = x /= y && sumProperDivisors x == y && sumProperDivisors y == x
sumAmicable :: (Integral a) => a -> a
sumAmicable n = sum [x | x <- [1 .. n - 1], amicable x $ sumProperDivisors x]
p021 :: IO ()
p021 = do
let result = sumAmicable 10000
putStrLn $
"Project Euler, Problem 21\n"
++ "Answer: "
++ show result

28
Haskell/src/P022.hs Normal file
View File

@ -0,0 +1,28 @@
-- Using p022_names.txt, a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order.
-- Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.
--
-- For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list.
-- So, COLIN would obtain a score of 938 × 53 = 49714.
--
-- What is the total of all the name scores in the file?
module P022 (p022) where
import Data.Char (ord)
import Data.List (sort)
import Data.List.Split (splitOn)
nameScore :: String -> Int
nameScore s =
let a = ord 'A' - 1
in sum $ map ((\x -> x - a) . ord) s
p022 :: IO ()
p022 = do
contents <- readFile "p022_names.txt"
let name_scores = map nameScore . sort . splitOn "," $ filter (/= '"') contents
result = sum $ zipWith (*) name_scores [1 ..]
putStrLn $
"Project Euler, Problem 22\n"
++ "Answer: "
++ show result

36
Haskell/src/P023.hs Normal file
View File

@ -0,0 +1,36 @@
-- A perfect number is a number for which the sum of its proper divisors is exactly equal to the number.
-- For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
--
-- A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
--
-- As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24.
-- By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers.
-- However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed
-- as the sum of two abundant numbers is less than this limit.
--
-- Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
module P023 (p023) where
import Data.List ((\\))
import qualified Data.Set as Set
import ProjectEuler (sumProperDivisors)
isAbundant :: (Integral a) => a -> Bool
isAbundant n = sumProperDivisors n > n
abundantSums :: (Integral a) => [a]
abundantSums = Set.toList $ Set.fromList [x + y | x <- abundantList, y <- abundantList, x + y <= 28123, y >= x]
where
abundantList = [x | x <- [12 .. 28123], isAbundant x]
sumNotAbundant :: (Integral a) => a
sumNotAbundant = sum $ [1 .. 28123] \\ abundantSums
p023 :: IO ()
p023 = do
let result = sumNotAbundant
putStrLn $
"Project Euler, Problem 23\n"
++ "Answer: "
++ show result

18
Haskell/src/P024.hs Normal file
View File

@ -0,0 +1,18 @@
-- A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4.
-- If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:
--
-- 012 021 102 120 201 210
--
-- What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
module P024 (p024) where
import Data.List (permutations, sort)
p024 :: IO ()
p024 = do
let result = sort (permutations "0123456789") !! 999999
putStrLn $
"Project Euler, Problem 24\n"
++ "Answer: "
++ result

35
Haskell/src/P025.hs Normal file
View File

@ -0,0 +1,35 @@
-- The Fibonacci sequence is defined by the recurrence relation:
--
-- Fn = Fn1 + Fn2, where F1 = 1 and F2 = 1.
-- Hence the first 12 terms will be:
-- F1 = 1
-- F2 = 1
-- F3 = 2
-- F4 = 3
-- F5 = 5
-- F6 = 8
-- F7 = 13
-- F8 = 21
-- F9 = 34
-- F10 = 55
-- F11 = 89
-- F12 = 144
--
-- The 12th term, F12, is the first term to contain three digits.
--
-- What is the index of the first term in the Fibonacci sequence to contain 1000 digits?
module P025 (p025) where
fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
thousandDigitFib = length $ takeWhile (\x -> length (show x) < 1000) fibs
p025 :: IO ()
p025 = do
let result = thousandDigitFib
putStrLn $
"Project Euler, Problem 25\n"
++ "Answer: "
++ show result

44
Haskell/src/P026.hs Normal file
View File

@ -0,0 +1,44 @@
-- A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
--
-- 1/2 = 0.5
-- 1/3 = 0.(3)
-- 1/4 = 0.25
-- 1/5 = 0.2
-- 1/6 = 0.1(6)
-- 1/7 = 0.(142857)
-- 1/8 = 0.125
-- 1/9 = 0.(1)
-- 1/10 = 0.1
--
-- Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.
--
-- Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.
module P026 (p026) where
removeFactor :: (Integral a) => a -> a -> a
removeFactor f n
| n `mod` f /= 0 = n
| otherwise = removeFactor f (n `div` f)
findCycleLengthRecursive :: (Integral a) => a -> a -> a -> a
findCycleLengthRecursive n j k
| n == 1 = 0
| k `mod` n == 0 = j
| otherwise = findCycleLengthRecursive n (j + 1) (k * 10 + 9)
findCycleLength :: (Integral a) => a -> a
findCycleLength n = findCycleLengthRecursive ((removeFactor 2 . removeFactor 5) n) 1 9
maxRepeatingCycle :: (Integral a) => a -> a -> a
maxRepeatingCycle a b = snd . maximum $ zip xs [1 ..]
where
xs = map findCycleLength [a .. b]
p026 :: IO ()
p026 = do
let result = maxRepeatingCycle 1 999
putStrLn $
"Project Euler, Problem 26\n"
++ "Answer: "
++ show result

43
Haskell/src/P027.hs Normal file
View File

@ -0,0 +1,43 @@
-- Euler discovered the remarkable quadratic formula:
--
-- n^2+n+41
--
-- It turns out that the formula will produce 40 primes for the consecutive integer values 0≤n≤39. However, when n=40,402+40+41=40(40+1)+41 is
-- divisible by 41, and certainly when n=41,412+41+41 is clearly divisible by 41.
--
-- The incredible formula n^279n+1601 was discovered, which produces 80 primes for the consecutive values 0≤n≤79.
-- The product of the coefficients, 79 and 1601, is 126479.
--
-- Considering quadratics of the form:
--
-- n^2+an+b, where |a|<1000 and |b|≤1000
--
-- where |n| is the modulus/absolute value of n
-- e.g. |11|=11 and |4|=4
--
-- Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n,
-- starting with n=0.
module P027 (p027) where
import Data.Function (on)
import Data.List (maximumBy)
import ProjectEuler (isPrime)
findLengthPrimeSequence :: Int -> Int -> Int
findLengthPrimeSequence a b = length $ takeWhile isPrime [n * n + a * n + b | n <- [0 ..]]
findCoefficients =
let as = [-999 .. 999]
bs = filter isPrime [2 .. 1000]
cs = [(a, b) | a <- as, b <- bs]
in fst $ maximumBy (compare `on` snd) [(c, l) | c <- cs, let l = uncurry findLengthPrimeSequence c]
p027 :: IO ()
p027 = do
let coefficients = findCoefficients
result = uncurry (*) coefficients
putStrLn $
"Project Euler, Problem 27\n"
++ "Answer: "
++ show result

27
Haskell/src/P029.hs Normal file
View File

@ -0,0 +1,27 @@
-- Consider all integer combinations of ab for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5:
--
-- 2^2=4, 2^3=8, 2^4=16, 2^5=32
-- 3^2=9, 3^3=27, 3^4=81, 3^5=243
-- 4^2=16, 4^3=64, 4^4=256, 4^5=1024
-- 5^2=25, 5^3=125, 5^4=625, 5^5=3125
--
-- If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:
--
-- 4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125
--
-- How many distinct terms are in the sequence generated by ab for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?
module P029 (p029) where
import Data.List (nub)
powerCombinations :: (Integral a) => a -> [a]
powerCombinations n = nub [x ^ y | x <- [2 .. n], y <- [2 .. n]]
p029 :: IO ()
p029 = do
let result = length $ powerCombinations 100
putStrLn $
"Project Euler, Problem 29\n"
++ "Answer: "
++ show result

29
Haskell/src/P030.hs Normal file
View File

@ -0,0 +1,29 @@
-- Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits:
--
-- 1634 = 1^4 + 6^4 + 3^4 + 4^4
-- 8208 = 8^4 + 2^4 + 0^4 + 8^4
-- 9474 = 9^4 + 4^4 + 7^4 + 4^4
--
-- As 1 = 1^4 is not a sum it is not included.
--
-- The sum of these numbers is 1634 + 8208 + 9474 = 19316.
--
-- Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.
module P030 (p030) where
import Data.Char (digitToInt)
sumNthPowerDigit :: Int -> Int -> Int
sumNthPowerDigit p n = sum [x ^ p | x <- map digitToInt (show n)]
equalsSumNthPowerDigit :: Int -> Int -> Bool
equalsSumNthPowerDigit p n = n == sumNthPowerDigit p n
p030 :: IO ()
p030 = do
let result = sum $ filter (equalsSumNthPowerDigit 5) [10 .. 354295]
putStrLn $
"Project Euler, Problem 30\n"
++ "Answer: "
++ show result

29
Haskell/src/P034.hs Normal file
View File

@ -0,0 +1,29 @@
-- 145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145.
--
-- Find the sum of all numbers which are equal to the sum of the factorial of their digits.
--
-- Note: as 1! = 1 and 2! = 2 are not sums they are not included.
module P034 (p034) where
import Data.Char
factorial :: (Integral a) => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)
factDigits :: [Int]
factDigits = map factorial [0 .. 9]
equalsDigitFactorial :: Int -> Bool
equalsDigitFactorial n =
let fact_digit_sum = sum $ [factDigits !! x | x <- map digitToInt (show n)]
in fact_digit_sum == n
p034 :: IO ()
p034 = do
let result = sum $ filter equalsDigitFactorial [10 .. 9999999]
putStrLn $
"Project Euler, Problem 34\n"
++ "Answer: "
++ show result

26
Haskell/src/P035.hs Normal file
View File

@ -0,0 +1,26 @@
-- The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime.
--
-- There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97.
--
-- How many circular primes are there below one million?
module P035 (p035) where
import Data.List (inits, tails)
import ProjectEuler (isPrime, primeSieve)
isCircularPrime :: Int -> Bool
isCircularPrime n
| n == 2 = True
| any (`elem` ['0', '2' .. '8']) (show n) = False
| all (isPrime . read) rotations = True
| otherwise = False
where
rotations = zipWith (++) (tails (show n)) (init (inits (show n)))
p035 :: IO ()
p035 = do
let result = length $ filter isCircularPrime (takeWhile (< 1000000) primeSieve)
putStrLn $
"Project Euler, Problem 35\n"
++ "Answer: "
++ show result

23
Haskell/src/P036.hs Normal file
View File

@ -0,0 +1,23 @@
-- The decimal number, 585 = 1001001001_2 (binary), is palindromic in both bases.
--
-- Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2.
--
-- (Please note that the palindromic number, in either base, may not include leading zeros.)
module P036 (p036) where
toBinary :: Int -> [Int]
toBinary 0 = []
toBinary 1 = [1]
toBinary n = toBinary (n `div` 2) ++ [n `mod` 2]
doublePalindrome :: Int -> Bool
doublePalindrome n = show n == reverse (show n) && toBinary n == reverse (toBinary n)
p036 :: IO ()
p036 = do
let result = sum $ filter doublePalindrome [1 .. 999999]
putStrLn $
"Project Euler, Problem 36\n"
++ "Answer: "
++ show result

19
Haskell/src/P041.hs Normal file
View File

@ -0,0 +1,19 @@
-- We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital
-- and is also prime.
--
-- What is the largest n-digit pandigital prime that exists?
module P041 (p041) where
import ProjectEuler (isPandigital, isPrime)
maxPandigitalPrime :: Integer
maxPandigitalPrime = head $ filter isPrime (filter isPandigital [7654321, 7654319 ..])
p041 :: IO ()
p041 = do
let result = maxPandigitalPrime
putStrLn $
"Project Euler, Problem 41\n"
++ "Answer: "
++ show result

18
Haskell/src/P052.hs Normal file
View File

@ -0,0 +1,18 @@
-- It can be seen that the number, 125874, and its double, 251748, contain exactly the same digits, but in a different order.
--
-- Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits.
module P052 (p052) where
import Data.List (sort)
smallestPermutedMultiples :: Integer
smallestPermutedMultiples = head [x | x <- [1 ..], sort (show x) == sort (show (2 * x)), sort (show x) == sort (show (3 * x)), sort (show x) == sort (show (4 * x)), sort (show x) == sort (show (5 * x)), sort (show x) == sort (show (6 * x))]
p052 :: IO ()
p052 = do
let result = smallestPermutedMultiples
putStrLn $
"Project Euler, Problem 52\n"
++ "Answer: "
++ show result

249
Haskell/src/P054.hs Normal file
View File

@ -0,0 +1,249 @@
-- In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in the following way:
--
-- High Card: Highest value card.
-- One Pair: Two cards of the same value.
-- Two Pairs: Two different pairs.
-- Three of a Kind: Three cards of the same value.
-- Straight: All cards are consecutive values.
-- Flush: All cards of the same suit.
-- Full House: Three of a kind and a pair.
-- Four of a Kind: Four cards of the same value.
-- Straight Flush: All cards are consecutive values of same suit.
-- Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
-- The cards are valued in the order:
-- 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
--
-- If two players have the same ranked hands then the rank made up of the highest value wins; for example, a pair of eights beats a pair of fives
-- (see example 1 below). But if two ranks tie, for example, both players have a pair of queens, then highest cards in each hand are compared
-- (see example 4 below); if the highest cards tie then the next highest cards are compared, and so on.
--
-- Consider the following five hands dealt to two players:
--
-- Hand Player 1 Player 2 Winner
-- 1 5H 5C 6S 7S KD 2C 3S 8S 8D TD Player 2
-- Pair of Fives Pair of Eights
--
-- 2 5D 8C 9S JS AC 2C 5C 7D 8S QH Player 1
-- Highest card Ace Highest card Queen
--
-- 3 2D 9C AS AH AC 3D 6D 7D TD QD Player 2
-- Three Aces Flush with Diamonds
--
-- 4 4D 6S 9H QH QC 3D 6D 7H QD QS Player 1
-- Pair of Queens Pair of Queens
-- Highest card Nine Highest card Seven
--
-- 5 2H 2D 4C 4D 4S 3C 3D 3S 9S 9D Player 1
-- Full House Full House
-- With Three Fours With Three Threes
--
-- The file, p054_poker.txt, contains one-thousand random hands dealt to two players. Each line of the file contains ten cards
-- (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards.
-- You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no specific order,
-- and in each hand there is a clear winner.
--
-- How many hands does Player 1 win?
module P054 (p054) where
import Data.Function (on)
import Data.List (groupBy, maximumBy, minimumBy, sort, sortBy)
import Data.Maybe (fromJust)
data Value = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten | Jack | Queen | King | Ace
deriving (Eq, Ord, Show, Bounded, Enum)
data Suit = Hearts | Diamonds | Clubs | Spades deriving (Eq, Show)
data Card = Card
{ value :: Maybe Value,
suit :: Maybe Suit
}
deriving (Eq, Show)
instance Ord Card where
(Card v1 _) `compare` (Card v2 _) = v1 `compare` v2
type Hand = [Card]
data PokerGame = PokerGame
{ player1 :: Hand,
player2 :: Hand
}
deriving (Eq, Show)
getValue :: Char -> Maybe Value
getValue '2' = Just Two
getValue '3' = Just Three
getValue '4' = Just Four
getValue '5' = Just Five
getValue '6' = Just Six
getValue '7' = Just Seven
getValue '8' = Just Eight
getValue '9' = Just Nine
getValue 'T' = Just Ten
getValue 'J' = Just Jack
getValue 'Q' = Just Queen
getValue 'K' = Just King
getValue 'A' = Just Ace
getValue _ = Nothing
getSuit :: Char -> Maybe Suit
getSuit 'H' = Just Hearts
getSuit 'D' = Just Diamonds
getSuit 'C' = Just Clubs
getSuit 'S' = Just Spades
getSuit _ = Nothing
readCard :: String -> Card
readCard (v : s : _) = Card {value = getValue v, suit = getSuit s}
readGame :: String -> PokerGame
readGame g = PokerGame {player1 = map readCard (take 5 (words g)), player2 = map readCard (take 5 (reverse (words g)))}
royalFlush :: Hand -> Bool
royalFlush h =
let hs = sort h
in length (head (groupBy ((==) `on` suit) hs)) == 5 && [Ten .. Ace] == map (fromJust . value) hs
straightFlush :: Hand -> Bool
straightFlush h =
let hs@(x : _) = sort h
start = fromJust . value $ x
in length (head (groupBy ((==) `on` suit) hs)) == 5
&& take 5 [start ..] == map (fromJust . value) hs
fourOfAKind :: Hand -> Bool
fourOfAKind h =
length (maximumBy (compare `on` length) (groupBy ((==) `on` value) (sort h))) == 4
fullHouse :: Hand -> Bool
fullHouse h =
let hs = sort h
in length (minimumBy (compare `on` length) (groupBy ((==) `on` value) hs)) == 2
&& length (maximumBy (compare `on` length) (groupBy ((==) `on` value) hs)) == 3
flush :: Hand -> Bool
flush h =
length (groupBy ((==) `on` suit) h) == 1
straight :: Hand -> Bool
straight h =
let hs@(x : _) = sort h
start = fromJust . value $ x
in take 5 [start ..] == map (fromJust . value) hs
three :: Hand -> Bool
three h =
length (maximumBy (compare `on` length) (groupBy ((==) `on` value) (sort h))) == 3
twoPairs :: Hand -> Bool
twoPairs h =
let hs = sort h
g_hs = sortBy (flip compare `on` length) (groupBy ((==) `on` value) hs)
in length (head g_hs) == 2 && length (head (tail g_hs)) == 2
pair :: Hand -> Bool
pair h =
length (maximumBy (compare `on` length) (groupBy ((==) `on` value) (sort h))) == 2
findPairVal :: Hand -> Card
findPairVal h =
head $ concat $ sortBy (flip compare `on` length) (groupBy ((==) `on` value) (sort h))
playGame :: PokerGame -> Int
playGame g
| royalFlush $ player1 g = 1
| royalFlush $ player2 g = -1
| straightFlush (player1 g) && not (straightFlush (player2 g)) = 1
| straightFlush (player2 g) && not (straightFlush (player1 g)) = -1
| straightFlush (player1 g) && straightFlush (player2 g) =
if minimum (player1 g) > minimum (player2 g) then 1 else -1
| fourOfAKind (player1 g) && not (fourOfAKind (player2 g)) = 1
| fourOfAKind (player2 g) && not (fourOfAKind (player1 g)) = -1
| fourOfAKind (player1 g) && fourOfAKind (player2 g) =
let (_ : x : _) = sort $ player1 g
(_ : y : _) = sort $ player2 g
in if value x > value y then 1 else -1
| fullHouse (player1 g) && not (fullHouse (player2 g)) = 1
| fullHouse (player2 g) && not (fullHouse (player1 g)) = -1
| fullHouse (player1 g) && fullHouse (player2 g) =
let (_ : _ : x : _) = sort $ player1 g
(_ : _ : y : _) = sort $ player2 g
in if value x > value y then 1 else -1
| flush (player1 g) && not (flush (player2 g)) = 1
| flush (player2 g) && not (flush (player1 g)) = -1
| flush (player1 g) && flush (player2 g) =
if maximum (player1 g) > maximum (player2 g) then 1 else -1
| straight (player1 g) && not (straight (player2 g)) = 1
| straight (player2 g) && not (straight (player1 g)) = -1
| straight (player1 g) && straight (player2 g) =
if minimum (player1 g) > minimum (player2 g) then 1 else -1
| three (player1 g) && not (three (player2 g)) = 1
| three (player2 g) && not (three (player1 g)) = -1
| three (player1 g) && three (player2 g) =
let (_ : _ : x : _) = sort $ player1 g
(_ : _ : y : _) = sort $ player2 g
in if value x > value y then 1 else -1
| twoPairs (player1 g) && not (twoPairs (player2 g)) = 1
| twoPairs (player2 g) && not (twoPairs (player1 g)) = -1
| twoPairs (player1 g) && twoPairs (player2 g) =
let (v : w : x : y : z : _) = sort $ player1 g
(a : b : c : d : e : _) = sort $ player2 g
in if value y > value d
then 1
else
if value y < value d
then -1
else
if value w > value b
then 1
else
if value w < value b
then -1
else
if value z > value e
then 1
else
if value z < value e
then -1
else
if value x > value c
then 1
else
if value x < value c
then -1
else
if value v > value a
then 1
else -1
| pair (player1 g) && not (pair (player2 g)) = 1
| pair (player2 g) && not (pair (player1 g)) = -1
| pair (player1 g) && pair (player2 g) =
let p1 = findPairVal (player1 g)
p2 = findPairVal (player2 g)
xs = reverse . sort $ player1 g
ys = reverse . sort $ player2 g
in if p1 > p2
then 1
else
if p2 > p1
then -1
else
if xs > ys
then 1
else -1
| otherwise =
let xs = reverse . sort $ player1 g
ys = reverse . sort $ player2 g
in if xs > ys then 1 else -1
p054 :: IO ()
p054 = do
contents <- readFile "p054_poker.txt"
let games = map readGame (lines contents)
result = sum $ filter (== 1) $ map playGame games
putStrLn $
"Project Euler, Problem 54\n"
++ "Answer: "
++ show result

View File

@ -0,0 +1,49 @@
module ProjectEuler
( isPrime,
primeSieve,
lcmm,
digitSum,
sumProperDivisors,
countDivisors,
isPandigital,
)
where
import Data.Char (digitToInt)
import Data.List (nub)
import Data.List.Ordered (minus, unionAll)
isPrime :: (Integral n) => n -> Bool
isPrime 1 = False
isPrime 2 = True
isPrime 3 = True
isPrime n =
n > 0 && odd n && n `mod` 3 /= 0 && null [x | x <- candidates, n `mod` x == 0 || n `mod` (x + 2) == 0]
where
candidates = [5, 11 .. limit]
limit = floor (sqrt (fromIntegral n)) + 1
primeSieve :: (Integral n) => [n]
primeSieve = 2 : 3 : [5, 7 ..] `minus` unionAll [[p * p, p * p + 2 * p ..] | p <- tail primeSieve]
lcmm :: (Integral n) => [n] -> n
lcmm values
| length values == 2 = lcm (head values) (last values)
| otherwise = lcm (head values) (lcmm (tail values))
digitSum :: (Integral a, Show a) => a -> Int
digitSum n = sum $ map digitToInt $ show n
sumProperDivisors :: (Integral a) => a -> a
sumProperDivisors n = sum [if x /= y then x + y else x | x <- [2 .. floor $ sqrt $ fromIntegral n], let { y = n `div` x }, n `mod` x == 0] + 1
countDivisors :: (Integral a) => a -> Int
countDivisors n = length $ nub $ concat [[x, n `div` x] | x <- [1 .. limit], n `mod` x == 0]
where
limit = floor $ sqrt $ fromIntegral n
isPandigital :: Integer -> Bool
isPandigital n = n_length == length (nub n_char) && '0' `notElem` n_char && digitToInt (maximum n_char) == n_length
where
n_char = show n
n_length = length n_char