Done day 10
[advent-of-code-22.git] / advent10 / Main.hs
diff --git a/advent10/Main.hs b/advent10/Main.hs
new file mode 100644 (file)
index 0000000..764638f
--- /dev/null
@@ -0,0 +1,79 @@
+-- Writeup at https://work.njae.me.uk/2022/12/10/advent-of-code-2022-day-9/
+
+import AoC
+import Data.Text (Text)
+import qualified Data.Text.IO as TIO
+import Data.Attoparsec.Text hiding (take)
+import Control.Applicative
+import Data.List
+import Data.List.Split (chunksOf)
+
+data Operation = Noop | Addx Int
+  deriving (Show, Eq)
+
+type Signal = (Int, Int) -- during cycle, register
+
+main :: IO ()
+main = 
+  do  dataFileName <- getDataFileName
+      text <- TIO.readFile dataFileName
+      let ops = successfulParse text
+      let regVals = apply ops
+      print $ part1 regVals
+      putStrLn $ part2 regVals
+
+part1 :: [Signal] -> Int
+part1 regVals = calculateSixSignals $ extractSignals regVals
+
+part2 :: [Signal] -> String
+part2 regVals = unlines display
+  where pixels = map isLit regVals
+        rows = chunksOf 40 pixels
+        display = fmap (fmap showPixel) rows
+
+apply :: [Operation] -> [Signal]
+apply ops = zip [1..] $ scanl' (+) 1 $ concatMap applyOp ops
+
+applyOp :: Operation -> [Int]
+applyOp   Noop = [0]
+applyOp (Addx d) = [0, d]
+
+extractSignals :: [Signal] -> [Signal]
+extractSignals signals = filter (\(t, _n) -> (t + 20) `mod` 40 == 0) signals
+
+calculateSixSignals :: [Signal] -> Int
+calculateSixSignals signals = sum [ (t * n) 
+                                  | (t, n) <- signals
+                                  , t <= 220
+                                  ]
+
+
+isLit :: Signal -> Bool
+isLit (n, x) = abs (x - c) <= 1
+  where c = colummOf n
+
+colummOf :: Int -> Int
+-- colummOf n = (n - 1) `mod` 40 + 1
+colummOf n = (n - 1) `mod` 40
+
+showPixel :: Bool -> Char
+-- showPixel True = '#'
+-- showPixel False = '.'
+showPixel True = '█'
+showPixel False = ' '
+
+-- Parse the input file
+
+operationsP :: Parser [Operation]
+operationP, noopP, addxP :: Parser Operation
+
+operationsP = operationP `sepBy` endOfLine
+operationP = noopP <|> addxP
+noopP = Noop <$ "noop"
+addxP = Addx <$> ("addx " *> signed decimal)
+
+successfulParse :: Text -> [Operation]
+successfulParse input = 
+  case parseOnly operationsP input of
+    Left  _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
+    Right ops -> ops