Optimised day 19
[advent-of-code-22.git] / advent10 / Main.hs
1 -- Writeup at https://work.njae.me.uk/2022/12/13/advent-of-code-2022-day-10/
2
3 import AoC
4 import Data.Text (Text)
5 import qualified Data.Text.IO as TIO
6 import Data.Attoparsec.Text hiding (take)
7 import Control.Applicative
8 import Data.List
9 import Data.List.Split (chunksOf)
10
11 data Operation = Noop | Addx Int
12 deriving (Show, Eq)
13
14 type Signal = (Int, Int) -- during cycle, register
15
16 main :: IO ()
17 main =
18 do dataFileName <- getDataFileName
19 text <- TIO.readFile dataFileName
20 let ops = successfulParse text
21 let regVals = apply ops
22 print $ part1 regVals
23 putStrLn $ part2 regVals
24
25 part1 :: [Signal] -> Int
26 part1 = calculateSixSignals . extractSignals
27
28 part2 :: [Signal] -> String
29 part2 regVals = unlines display
30 where pixels = map (showPixel . isLit) regVals
31 display = chunksOf 40 pixels
32
33 apply :: [Operation] -> [Signal]
34 apply = zip [1..] . scanl' (+) 1 . concatMap applyOp
35
36 applyOp :: Operation -> [Int]
37 applyOp Noop = [0]
38 applyOp (Addx d) = [0, d]
39
40 extractSignals :: [Signal] -> [Signal]
41 extractSignals = filter (\(t, _n) -> (t + 20) `mod` 40 == 0)
42
43 calculateSixSignals :: [Signal] -> Int
44 calculateSixSignals signals = sum [ (t * n)
45 | (t, n) <- signals
46 , t <= 220
47 ]
48
49 isLit :: Signal -> Bool
50 isLit (n, x) = abs (x - c) <= 1
51 where c = colummOf n
52
53 colummOf :: Int -> Int
54 colummOf n = (n - 1) `mod` 40
55
56 showPixel :: Bool -> Char
57 -- showPixel True = '#'
58 -- showPixel False = '.'
59 showPixel True = '█'
60 showPixel False = ' '
61
62 -- Parse the input file
63
64 operationsP :: Parser [Operation]
65 operationP, noopP, addxP :: Parser Operation
66
67 operationsP = operationP `sepBy` endOfLine
68 operationP = noopP <|> addxP
69 noopP = Noop <$ "noop"
70 addxP = Addx <$> ("addx " *> signed decimal)
71
72 successfulParse :: Text -> [Operation]
73 successfulParse input =
74 case parseOnly operationsP input of
75 Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
76 Right ops -> ops