-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.hs
63 lines (50 loc) · 1.41 KB
/
run.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
60
61
62
63
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
import Control.Monad (guard)
import Data.Functor.Contravariant (Comparison(..))
import Data.List (sortBy)
import Data.List.Split (splitOn)
type N = Int
type Input = (Comparison N, [[N]])
-- Very, very ineffective, but fun :)
parseComp :: String -> Comparison N
parseComp input =
let [x, y] = map (read @N) $ splitOn "|" input
in Comparison . curry $ \case
(x', y') | x' == x && y' == y -> LT
| x' == y && y' == x -> GT
| otherwise -> EQ
parseUpdate :: String -> [N]
parseUpdate input = read @[N] $ "[" <> input <> "]"
parseAll :: String -> Input
parseAll input =
let [comps, xs] = splitOn [""] $ lines input
in (foldMap parseComp comps, map parseUpdate xs)
middle :: [a] -> a
middle xs =
let l = length xs
in xs !! (l `div` 2)
part1 :: Input -> N
part1 (comp, updates) =
sum
. map middle
. filter (\u -> sortBy (getComparison comp) u == u)
$ updates
part2 :: Input -> N
part2 (comp, updates) = sum do
u <- updates
let u' = sortBy (getComparison comp) u
guard $ u' /= u
pure $ middle u'
main :: IO ()
main = main' "input.txt"
exampleMain :: IO ()
exampleMain = main' "example.txt"
main' :: FilePath -> IO ()
main' file = do
input <- parseAll <$> readFile file
print (part1 input)
print (part2 input)