Fix Haskell code with ormolu

This commit is contained in:
daniele 2024-12-15 11:31:42 +01:00
parent 6ebb82fb8c
commit 751673989c
Signed by: fuxino
GPG Key ID: 981A2B2A3BBF5514
34 changed files with 540 additions and 430 deletions

View File

@ -1,12 +1,13 @@
module ProjectEuler
( isPrime
, primeSieve
, lcmm
, digitSum
, sumProperDivisors
, countDivisors
, isPandigital
) where
( isPrime,
primeSieve,
lcmm,
digitSum,
sumProperDivisors,
countDivisors,
isPandigital,
)
where
import Data.Char (digitToInt)
import Data.List (nub)
@ -17,29 +18,32 @@ 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
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]
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))
| 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
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
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
where
n_char = show n
n_length = length n_char

View File

@ -3,10 +3,13 @@
-- Find the sum of all the multiples of 3 or 5 below 1000.
sumMultiples :: Int
sumMultiples = sum $ filter p [1..999]
where p n = n `mod` 3 == 0 || n `mod` 5 == 0
sumMultiples = sum $ filter p [1 .. 999]
where
p n = n `mod` 3 == 0 || n `mod` 5 == 0
main = do
let result = sumMultiples
putStrLn $ "Project Euler, Problem 1\n"
++ "Answer: " ++ show result
let result = sumMultiples
putStrLn $
"Project Euler, Problem 1\n"
++ "Answer: "
++ show result

View File

@ -7,12 +7,14 @@
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib(n-2)
fib n = fib (n - 1) + fib (n - 2)
sumEvenFib :: Int
sumEvenFib = sum $ filter even $ takeWhile (<=4000000) (map fib [0..])
sumEvenFib = sum $ filter even $ takeWhile (<= 4000000) (map fib [0 ..])
main = do
let result = sumEvenFib
putStrLn $ "Project Euler, Problem 2\n"
++ "Answer: " ++ show result
let result = sumEvenFib
putStrLn $
"Project Euler, Problem 2\n"
++ "Answer: "
++ show result

View File

@ -5,11 +5,13 @@ 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]
| isPrime n = n
| even n = maxPrimeFactor $ n `div` 2
| otherwise = maxPrimeFactor $ n `div` head [i | i <- [3, 5 ..], n `mod` i == 0 && isPrime i]
main = do
let result = maxPrimeFactor 600851475143
putStrLn $ "Project Euler, Problem 3\n"
++ "Answer: " ++ show result
let result = maxPrimeFactor 600851475143
putStrLn $
"Project Euler, Problem 3\n"
++ "Answer: "
++ show result

View File

@ -7,9 +7,11 @@ isPalindrome n = show n == reverse (show n)
maxPalindrome :: Int
maxPalindrome =
maximum . filter isPalindrome $ (*) <$> [100..999] <*> [100..999]
maximum . filter isPalindrome $ (*) <$> [100 .. 999] <*> [100 .. 999]
main = do
let result = maxPalindrome
putStrLn $ "Project Euler, Problem 4\n"
++ "Answer: " ++ show result
let result = maxPalindrome
putStrLn $
"Project Euler, Problem 4\n"
++ "Answer: "
++ show result

View File

@ -5,6 +5,8 @@
import ProjectEuler (lcmm)
main = do
let result = lcmm [1..20]
putStrLn $ "Project Euler, Problem 5\n"
++ "Answer: " ++ show result
let result = lcmm [1 .. 20]
putStrLn $
"Project Euler, Problem 5\n"
++ "Answer: "
++ show result

View File

@ -8,12 +8,14 @@
--
-- 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.
-- Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.
sumSquareDiff :: Int -> Int
sumSquareDiff n = (sum [1..n] ^2) - sum (map (^2) [1..n])
sumSquareDiff n = (sum [1 .. n] ^ 2) - sum (map (^ 2) [1 .. n])
main = do
let result = sumSquareDiff 100
putStrLn $ "Project Euler, Problem 6\n"
++ "Answer: " ++ show result
let result = sumSquareDiff 100
putStrLn $
"Project Euler, Problem 6\n"
++ "Answer: "
++ show result

View File

@ -5,9 +5,11 @@
import ProjectEuler (isPrime)
nthPrime :: Int -> Int
nthPrime n = last $ take n [ x | x <- [1..], isPrime x ]
nthPrime n = last $ take n [x | x <- [1 ..], isPrime x]
main = do
let result = nthPrime 10001
putStrLn $ "Project Euler, Problem 7\n"
++ "Answer: " ++ show result
let result = nthPrime 10001
putStrLn $
"Project Euler, Problem 7\n"
++ "Answer: "
++ show result

View File

@ -27,30 +27,33 @@ 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))
| length s < n = -1
| otherwise = max (product (map digitToInt (take n s))) (nDigitProduct n (tail s))
main = 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
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

View File

@ -9,12 +9,14 @@
-- Find the product abc.
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]
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
main = do
let result = prodTriplet $ pythagoreanTriplet 1000
putStrLn $ "Project Euler, Problem 9\n"
++ "Answer: " ++ show result
let result = prodTriplet $ pythagoreanTriplet 1000
putStrLn $
"Project Euler, Problem 9\n"
++ "Answer: "
++ show result

View File

@ -5,6 +5,8 @@
import ProjectEuler (primeSieve)
main = do
let result = sum $ takeWhile (<2000000) primeSieve
putStrLn $ "Project Euler, Problem 10\n"
++ "Answer: " ++ show result
let result = sum $ takeWhile (< 2000000) primeSieve
putStrLn $
"Project Euler, Problem 10\n"
++ "Answer: "
++ show result

View File

@ -29,38 +29,44 @@ 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))
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))
maxProd4 [x, y, z] = 0
maxProd4 (w : x : y : z : xs) = max (w * x * y * z) (maxProd4 (x : y : z : xs))
main = 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
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

View File

@ -21,12 +21,14 @@ import Data.List (nub)
import ProjectEuler (countDivisors)
triangNumbers :: [Int]
triangNumbers = scanl1 (+) [1..]
triangNumbers = scanl1 (+) [1 ..]
triang500 :: Int
triang500 = head [ x | x <- triangNumbers, countDivisors x > 500 ]
triang500 = head [x | x <- triangNumbers, countDivisors x > 500]
main = do
let result = triang500
putStrLn $ "Project Euler, Problem 12\n"
++ "Answer: " ++ show result
let result = triang500
putStrLn $
"Project Euler, Problem 12\n"
++ "Answer: "
++ show result

View File

@ -105,107 +105,112 @@ firstDigitsSum :: Int -> [Integer] -> Int
firstDigitsSum n xs = read . take n . show $ sum xs
main = 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
]
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
putStrLn $
"Project Euler, Problem 13\n"
++ "Answer: "
++ show result

View File

@ -17,13 +17,15 @@
collatz :: Int -> [Int]
collatz 1 = [1]
collatz n
| even n = n:collatz (n `div` 2)
| odd n = n:collatz (3 * n + 1)
| 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]
maxCollatzLength n = snd $ maximum $ zip [length (collatz x) | x <- [1 .. n - 1]] [1 .. n - 1]
main = do
let result = maxCollatzLength 1000000
putStrLn $ "Project Euler, Problem 14\n"
++ "Answer: " ++ show result
let result = maxCollatzLength 1000000
putStrLn $
"Project Euler, Problem 14\n"
++ "Answer: "
++ show result

View File

@ -6,6 +6,8 @@ factorial 0 = 1
factorial n = n * factorial (n - 1)
main = do
let result = factorial 40 `div` factorial 20 ^ 2
putStrLn $ "Project Euler, Problem 15\n"
++ "Answer: " ++ show result
let result = factorial 40 `div` factorial 20 ^ 2
putStrLn $
"Project Euler, Problem 15\n"
++ "Answer: "
++ show result

View File

@ -5,6 +5,8 @@
import ProjectEuler (digitSum)
main = do
let result = digitSum $ 2 ^ 1000
putStrLn $ "Project Euler, Problem 16\n"
++ "Answer: " ++ show result
let result = digitSum $ 2 ^ 1000
putStrLn $
"Project Euler, Problem 16\n"
++ "Answer: "
++ show result

View File

@ -11,15 +11,18 @@
--
-- How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?
import Data.Time.Calendar (Day, DayOfWeek(Sunday), dayOfWeek, fromGregorian)
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
countSundaysFirst start end =
let days = [start .. end]
in length $ filter (\x -> dayOfWeek x == Sunday && [last (init (show x)), last (show x)] == "01") days
main = 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
let startDate = fromGregorian 1901 1 1
endDate = fromGregorian 2000 12 31
result = countSundaysFirst startDate endDate
putStrLn $
"Project Euler, Problem 19\n"
++ "Answer: "
++ show result

View File

@ -12,6 +12,8 @@ factorial 0 = 1
factorial n = n * factorial (n - 1)
main = do
let result = digitSum $ factorial 100
putStrLn $ "Project Euler, Problem 20\n"
++ "Answer: " ++ show result
let result = digitSum $ factorial 100
putStrLn $
"Project Euler, Problem 20\n"
++ "Answer: "
++ show result

View File

@ -9,15 +9,17 @@
import ProjectEuler (sumProperDivisors)
properDivisors :: (Integral a) => a -> [a]
properDivisors n = [ x | x <- [1..n-1], n `mod` x == 0]
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 ]
sumAmicable n = sum [x | x <- [1 .. n - 1], amicable x $ sumProperDivisors x]
main = do
let result = sumAmicable 10000
putStrLn $ "Project Euler, Problem 21\n"
++ "Answer: " ++ show result
let result = sumAmicable 10000
putStrLn $
"Project Euler, Problem 21\n"
++ "Answer: "
++ show result

View File

@ -11,12 +11,15 @@ 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
nameScore s =
let a = ord 'A' - 1
in sum $ map ((\x -> x - a) . ord) s
main = 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
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

View File

@ -11,20 +11,22 @@
-- Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
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 ]
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
sumNotAbundant = sum $ [1 .. 28123] \\ abundantSums
main = do
let result = sumNotAbundant
putStrLn $ "Project Euler, Problem 23\n"
++ "Answer: " ++ show result
let result = sumNotAbundant
putStrLn $
"Project Euler, Problem 23\n"
++ "Answer: "
++ show result

View File

@ -5,9 +5,11 @@
--
-- What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?
import Data.List (sort, permutations)
import Data.List (permutations, sort)
main = do
let result = sort (permutations "0123456789") !! 999999
putStrLn $ "Project Euler, Problem 24\n"
++ "Answer: " ++ result
let result = sort (permutations "0123456789") !! 999999
putStrLn $
"Project Euler, Problem 24\n"
++ "Answer: "
++ result

View File

@ -20,11 +20,13 @@
-- What is the index of the first term in the Fibonacci sequence to contain 1000 digits?
fibs :: [Integer]
fibs = 0:1:zipWith (+) fibs (tail fibs)
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
thousandDigitFib = length $ takeWhile (\x -> length (show x) < 1000) fibs
main = do
let result = thousandDigitFib
putStrLn $ "Project Euler, Problem 25\n"
++ "Answer: " ++ show result
main = do
let result = thousandDigitFib
putStrLn $
"Project Euler, Problem 25\n"
++ "Answer: "
++ show result

View File

@ -16,23 +16,26 @@
removeFactor :: (Integral a) => a -> a -> a
removeFactor f n
| n `mod` f /= 0 = n
| otherwise = removeFactor f (n `div` f)
| 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)
| n == 1 = 0
| k `mod` n == 0 = j
| otherwise = findCycleLengthRecursive n (j + 1) (k * 10 + 9)
findCycleLength :: (Integral a) => a -> a
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]
maxRepeatingCycle :: (Integral a) => a -> a -> a
maxRepeatingCycle a b = snd . maximum $ zip xs [1 ..]
where
xs = map findCycleLength [a .. b]
main = do
let result = maxRepeatingCycle 1 999
putStrLn $ "Project Euler, Problem 26\n"
++ "Answer: " ++ show result
let result = maxRepeatingCycle 1 999
putStrLn $
"Project Euler, Problem 26\n"
++ "Answer: "
++ show result

View File

@ -18,20 +18,23 @@
-- 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.
import Data.List (maximumBy)
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..] ]
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 ]
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]
main = do
let coefficients = findCoefficients
result = uncurry (*) coefficients
putStrLn $ "Project Euler, Problem 27\n"
++ "Answer: " ++ show result
let coefficients = findCoefficients
result = uncurry (*) coefficients
putStrLn $
"Project Euler, Problem 27\n"
++ "Answer: "
++ show result

View File

@ -13,9 +13,11 @@
import Data.List (nub)
powerCombinations :: (Integral a) => a -> [a]
powerCombinations n = nub [ x^y | x <- [2..n], y <- [2..n] ]
powerCombinations n = nub [x ^ y | x <- [2 .. n], y <- [2 .. n]]
main = do
let result = length $ powerCombinations 100
putStrLn $ "Project Euler, Problem 29\n"
++ "Answer: " ++ show result
let result = length $ powerCombinations 100
putStrLn $
"Project Euler, Problem 29\n"
++ "Answer: "
++ show result

View File

@ -13,12 +13,14 @@
import Data.Char (digitToInt)
sumNthPowerDigit :: Int -> Int -> Int
sumNthPowerDigit p n = sum [ x^p | x <- map digitToInt (show n) ]
sumNthPowerDigit p n = sum [x ^ p | x <- map digitToInt (show n)]
equalsSumNthPowerDigit :: Int -> Int -> Bool
equalsSumNthPowerDigit p n = n == sumNthPowerDigit p n
main = do
let result = sum $ filter (equalsSumNthPowerDigit 5) [10..354295]
putStrLn $ "Project Euler, Problem 30\n"
++ "Answer: " ++ show result
let result = sum $ filter (equalsSumNthPowerDigit 5) [10 .. 354295]
putStrLn $
"Project Euler, Problem 30\n"
++ "Answer: "
++ show result

View File

@ -11,13 +11,16 @@ factorial 0 = 1
factorial n = n * factorial (n - 1)
factDigits :: [Int]
factDigits = map factorial [0..9]
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
equalsDigitFactorial n =
let fact_digit_sum = sum $ [factDigits !! x | x <- map digitToInt (show n)]
in fact_digit_sum == n
main = do
let result = sum $ filter equalsDigitFactorial [10..9999999]
putStrLn $ "Project Euler, Problem 34\n"
++ "Answer: " ++ show result
let result = sum $ filter equalsDigitFactorial [10 .. 9999999]
putStrLn $
"Project Euler, Problem 34\n"
++ "Answer: "
++ show result

View File

@ -9,15 +9,16 @@ 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)))
--isCircularPrime n = let rotations = zipWith (++) (tails (show n)) (init (inits (show n)))
-- in all (isPrime . read) rotations
| 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)))
main = do
let result = length $ filter isCircularPrime (takeWhile (<1000000) primeSieve)
putStrLn $ "Project Euler, Problem 35\n"
++ "Answer: " ++ show result
let result = length $ filter isCircularPrime (takeWhile (< 1000000) primeSieve)
putStrLn $
"Project Euler, Problem 35\n"
++ "Answer: "
++ show result

View File

@ -13,6 +13,8 @@ doublePalindrome :: Int -> Bool
doublePalindrome n = show n == reverse (show n) && toBinary n == reverse (toBinary n)
main = do
let result = sum $ filter doublePalindrome [1..999999]
putStrLn $ "Project Euler, Problem 36\n"
++ "Answer: " ++ show result
let result = sum $ filter doublePalindrome [1 .. 999999]
putStrLn $
"Project Euler, Problem 36\n"
++ "Answer: "
++ show result

View File

@ -3,12 +3,14 @@
--
-- What is the largest n-digit pandigital prime that exists?
import ProjectEuler (isPrime, isPandigital)
import ProjectEuler (isPandigital, isPrime)
maxPandigitalPrime :: Integer
maxPandigitalPrime = head $ filter isPrime (filter isPandigital [7654321,7654319..])
maxPandigitalPrime = head $ filter isPrime (filter isPandigital [7654321, 7654319 ..])
main = do
let result = maxPandigitalPrime
putStrLn $ "Project Euler, Problem 41\n"
++ "Answer: " ++ show result
let result = maxPandigitalPrime
putStrLn $
"Project Euler, Problem 41\n"
++ "Answer: "
++ show result

View File

@ -4,9 +4,11 @@
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)) ]
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))]
main = do
let result = smallestPermutedMultiples
putStrLn $ "Project Euler, Problem 52\n"
++ "Answer: " ++ show result
let result = smallestPermutedMultiples
putStrLn $
"Project Euler, Problem 52\n"
++ "Answer: "
++ show result

View File

@ -44,26 +44,31 @@
--
-- How many hands does Player 1 win?
import Data.List (sort, sortBy, groupBy, minimumBy, maximumBy)
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)
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)
data Card = Card
{ value :: Maybe Value,
suit :: Maybe Suit
}
deriving (Eq, Show)
instance Ord Card where
(Card v1 _) `compare` (Card v2 _) = v1 `compare` v2
(Card v1 _) `compare` (Card v2 _) = v1 `compare` v2
type Hand = [Card]
data PokerGame = PokerGame { player1 :: Hand
, player2 :: Hand
} deriving (Eq, Show)
data PokerGame = PokerGame
{ player1 :: Hand,
player2 :: Hand
}
deriving (Eq, Show)
getValue :: Char -> Maybe Value
getValue '2' = Just Two
@ -89,129 +94,153 @@ getSuit 'S' = Just Spades
getSuit _ = Nothing
readCard :: String -> Card
readCard (v:s:_) = Card{value=getValue v,suit=getSuit s}
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)))}
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
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
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
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
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
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
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
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
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
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))
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
| 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
main = 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
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