1 -- Writeup at https://work.njae.me.uk/2021/12/13/advent-of-code-2021-day-13/
4 import qualified Data.Text.IO as TIO
6 import Data.Attoparsec.Text
7 import Control.Applicative
9 import qualified Data.Set as S
10 -- import Data.Set ((\\))
11 import Linear (V2(..), (^+^))
16 type Sheet = S.Set Coord
19 deriving (Eq, Ord, Show)
21 data Fold = Fold Axis Int
22 deriving (Eq, Ord, Show)
26 do text <- TIO.readFile "data/advent13.txt"
27 let (sheet, folds) = successfulParse text
28 print $ part1 sheet folds
29 putStrLn $ part2 sheet folds
31 part1 :: Sheet -> [Fold] -> Int
32 part1 sheet folds = S.size $ doFold sheet $ head folds
34 part2 :: Sheet -> [Fold] -> String
35 part2 sheet folds = showSheet foldedSheet
36 where foldedSheet = foldl' doFold sheet folds
38 doFold :: Sheet -> Fold -> Sheet
39 doFold sheet (Fold X i) = S.union left foldedRight
40 where (left, right) = S.partition ((<= i) . getX) sheet
41 foldedRight = S.map foldDot right
42 foldDot (V2 x y) = V2 (i - (x - i)) y
44 doFold sheet (Fold Y i) = S.union top foldedBottom
45 where (top, bottom) = S.partition ((<= i) . getY) sheet
46 foldedBottom = S.map foldDot bottom
47 foldDot (V2 x y) = V2 x (i - (y - i))
56 showSheet :: Sheet -> String
57 showSheet sheet = unlines [ concat [showPoint (V2 x y) | x <- ([0..maxX] :: [Int])
58 ] | y <- ([0..maxY] :: [Int]) ]
59 where showPoint here = if here `S.member` sheet then "█" else " "
60 maxX = S.findMax $ S.map getX sheet
61 maxY = S.findMax $ S.map getY sheet
64 -- Parse the input file
66 inputP = (,) <$> sheetP <* many1 endOfLine <*> foldsP
68 sheetP = S.fromList <$> dotP `sepBy` endOfLine
69 dotP = V2 <$> decimal <* "," <*> decimal
71 foldsP = foldP `sepBy` endOfLine
72 foldP = Fold <$> ("fold along " *> axisP) <* "=" <*> decimal
74 axisP = ("x" *> pure X) <|> ("y" *> pure Y)
76 -- successfulParse :: Text -> (Integer, [Maybe Integer])
77 successfulParse input =
78 case parseOnly inputP input of
79 Left _err -> (S.empty, []) -- TIO.putStr $ T.pack $ parseErrorPretty err
80 Right indata -> indata