-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path03.hs
59 lines (49 loc) · 1.63 KB
/
03.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import Data.Char
import Data.List
import Text.ParserCombinators.Parsec
possible :: (Int, Int, Int) -> Bool
possible (x, y, z) = all possible' (permutations [x, y, z]) where
possible' xs = (xs !! 0) + (xs !! 1) > (xs !! 2)
countPossible :: [(Int, Int, Int)] -> Int
countPossible ts = length (filter possible ts)
-- Part 2.
stride :: Int -> [a] -> [a]
stride _ [] = []
stride n (x:xs) = x : stride n (drop (n-1) xs)
groupsOf3 :: [a] -> [(a, a, a)]
groupsOf3 xs = zip3 as bs cs where
as = stride 3 xs
bs = stride 3 (drop 1 xs)
cs = stride 3 (drop 2 xs)
reformatTriples :: [(Int, Int, Int)] -> [(Int, Int, Int)]
reformatTriples ts = groupsOf3 (a ++ b ++ c) where
(a, b, c) = unzip3 ts
-- Parser.
parseSeparator :: Parser ()
parseSeparator = skipMany (space <|> newline)
parseDecimal :: Parser Int
parseDecimal = convertDecimal <$> many1 digit where
convertDecimal = foldl' (\a i -> a * 10 + digitToInt i) 0
parseTriple :: Parser (Int, Int, Int)
parseTriple = do
parseSeparator
x <- parseDecimal
parseSeparator
y <- parseDecimal
parseSeparator
z <- parseDecimal
parseSeparator
return (x, y, z)
parseFile :: Parser [(Int, Int, Int)]
parseFile = do
result <- many parseTriple
eof
return result
-- Main.
main = do
input <- getContents
let program = parse parseFile "" input
let result1 = countPossible <$> program
putStrLn . show $ result1
let result2 = countPossible <$> reformatTriples <$> program
putStrLn . show $ result2