-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay13.hs
65 lines (52 loc) · 1.69 KB
/
Day13.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
module Day13
( part1
, part2
) where
import Data.List.Split (chunksOf, splitOn, splitWhen)
import qualified Data.Set as St (Set, findMax, fromList, map, member,
size)
import Linear.V2 (V2 (..))
import Text.Regex.TDFA (getAllTextMatches, (=~))
type Pos = V2 Int
type Page = St.Set Pos
type Instruction = (String, Int)
fold :: Instruction -> Page -> Page
fold (dir, val)
| dir == "x" =
St.map
(\(V2 a b) ->
if a < val
then V2 a b
else V2 (2 * val - a) b)
| dir == "y" =
St.map
(\(V2 a b) ->
if b < val
then V2 a b
else V2 a (2 * val - b))
parsePage :: [String] -> Page
parsePage = St.fromList . map ((\[a, b] -> V2 (read a) (read b)) . splitOn ",")
parseInstructions :: [String] -> [Instruction]
parseInstructions = map (\t -> (t =~ "[xy]", read (t =~ "[0-9]+")))
parseInput :: [[String]] -> (Page, [Instruction])
parseInput [a, b] = (parsePage a, parseInstructions b)
oneFold :: (Page, [Instruction]) -> Page
oneFold (page, a:as) = fold a page
foldAll :: (Page, [Instruction]) -> Page
foldAll (page, instructions) = foldl (flip fold) page instructions
render :: Page -> String
render page =
unlines . chunksOf (mx + 1) $
[ if V2 x y `St.member` page
then '#'
else '.'
| y <- [0 .. my]
, x <- [0 .. mx]
]
where
mx = St.findMax . St.map (\(V2 x _) -> x) $ page
my = St.findMax . St.map (\(V2 _ y) -> y) $ page
part1 :: Bool -> String -> String
part1 _ = show . St.size . oneFold . parseInput . splitWhen null . lines
part2 :: Bool -> String -> String
part2 _ = render . foldAll . parseInput . splitWhen null . lines