-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun.hs
102 lines (82 loc) · 2.61 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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
import AoC
import AoC.Grid
import GHC.Ix (unsafeIndex)
import Data.Vector (Vector)
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as VM
type N = Int
data Cucumber = East | South
deriving (Show, Eq, Ord, Enum, Bounded)
data Cell = Empty | Filled !Cucumber
deriving (Show, Eq, Ord)
type Grid = Vector Cell
parseAll :: String -> ((N, N), Grid)
parseAll input =
let ls = lines input
xm = maximum $ map length ls
ym = length ls
v = V.fromList $
[ f cell | row <- ls
, cell <- row
]
b = (ym - 1, xm - 1)
in (b, v)
where f = \case 'v' -> Filled South
'>' -> Filled East
'.' -> Empty
ix :: (N, N) -> (N, N) -> Int
ix b = unsafeIndex ((0, 0), b)
{-# INLINE ix #-}
unIx :: (N, N) -> Int -> (N, N)
unIx (_, xm) i = i `divMod` (xm + 1)
{-# INLINE unIx #-}
stepEast :: (N, N) -> Grid -> Grid
stepEast b@(_, xm) g = V.modify action g
where action v = V.iforM_ g \i current ->
let (y, x) = unIx b i
righti = ix b (y, (x + 1) `mod` (xm + 1))
currenti = ix b (y, x)
in
case (current, g V.! righti) of
(Filled East, Empty) ->
VM.write v currenti Empty *> VM.write v righti (Filled East)
_ -> pure ()
{-# INLINE action #-}
stepSouth :: (N, N) -> Grid -> Grid
stepSouth b@(ym, _) g = V.modify action g
where action v = V.iforM_ g \i current ->
let (y, x) = unIx b i
downi = ix b ((y + 1) `mod` (ym + 1), x)
currenti = ix b (y, x)
in
case (current, g V.! downi) of
(Filled South, Empty) ->
VM.write v currenti Empty *> VM.write v downi (Filled South)
_ -> pure ()
{-# INLINE action #-}
step :: (N, N) -> Grid -> Grid
step b = stepSouth b . stepEast b
{-# INLINE step #-}
asList :: (N, N) -> Grid -> [[Cell]]
asList b@(ym, xm) g =
[ [ g V.! ix b (y, x) | x <- [0..xm] ] | y <- [0..ym] ]
pp :: (N, N) -> Grid -> String
pp b = ppGrid f . asList b
where f = \case Filled East -> '>'
Filled South -> 'v'
Empty -> '.'
part1 :: ((N, N), Grid) -> Int
part1 (b, g) = fst $ fixpointi (step b) g
main :: IO ()
main = main' "input.txt"
exampleMain :: IO ()
exampleMain = main' "example.txt"
main' :: FilePath -> IO ()
main' file = do
input <- parseAll <$> readFile file
print (part1 input)