-
Notifications
You must be signed in to change notification settings - Fork 0
/
run.hs
73 lines (60 loc) · 2.24 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
64
65
66
67
68
69
70
71
72
73
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TupleSections #-}
import AoC
import AoC.Draw.Chars
import AoC.Grid
import Data.List (permutations, group, minimum, maximum, minimumBy, maximumBy)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HashMap
import Data.Void (Void)
import Text.Megaparsec
import Text.Megaparsec.Char
width :: Int
width = 50
height :: Int
height = 6
type Screen = MapGrid Bool
printScreen :: Screen -> String
printScreen = ppMapGrid (\case True -> 'X'
_ -> ' ')
data Inst = Rect Int Int
| RotRow Int Int
| RotCol Int Int
deriving Show
parseInst :: Parsec Void String Inst
parseInst = rect <|> row <|> col
where num = (read :: String -> Int) <$> some digitChar
rect = Rect <$> (string "rect " *> num)
<*> (char 'x' *> num)
row = RotRow <$> (string "rotate row y=" *> num)
<*> (string " by " *> num)
col = RotCol <$> (string "rotate column x=" *> num)
<*> (string " by " *> num)
unsafeRight (Right x) = x
parseAll = map unsafeRight .
map (parse parseInst "") . lines
update :: Inst -> Screen -> Screen
update (Rect w h) prev = HashMap.union rect prev
where rect = HashMap.fromList $ [((x, y), True) | x <- [0..w - 1], y <- [0..h - 1]]
update (RotRow y step) prev = foldr f prev (zip (map ((`mod` width) . (+step)) r) r)
where r = [0..width - 1]
f (xn, xo) m =
case HashMap.lookup (xo, y) prev of
Just v -> HashMap.insert (xn, y) v m
Nothing -> HashMap.insert (xn, y) False m
update (RotCol x step) prev = foldr f prev (zip (map ((`mod` height) . (+step)) r) r)
where r = [0..height - 1]
f (yn, yo) m =
case HashMap.lookup (x, yo) prev of
Just v -> HashMap.insert (x, yn) v m
Nothing -> HashMap.insert (x, yn) False m
exec :: [Inst] -> Screen
exec = foldl (flip update) HashMap.empty
part1 :: [Inst] -> Int
part1 = HashMap.foldl (\a v -> a + fromEnum v) 0 . exec
part2 :: [Inst] -> String
part2 = unsafeRight . readLetters . printScreen . exec
main = do
input <- parseAll <$> readFile "input.txt"
print (part1 input)
putStrLn (part2 input)