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