@@ -6,34 +6,36 @@ import qualified Data.Matrix as M
66import Day6.Guard (Guard (.. ))
77import qualified Day6.Guard as G
88
9- data Error = GuardNotFoundError
9+ data Error = GuardNotFoundError | InfiniteLoopError
1010 deriving (Eq , Show )
1111
1212partOne :: String -> Either Error Int
1313partOne input = do
1414 let labMap = parseLabMap input
1515 guard <- findGuard labMap
16- let route = predictGuardsRoute guard labMap
16+ route <- predictGuardsRoute guard labMap
1717 return (length route)
1818
1919partTwo :: String -> Either Error Int
2020partTwo input = do
2121 let labMap = parseLabMap input
2222 guard <- findGuard labMap
23+ route <- predictGuardsRoute guard labMap
2324 let initialPosition = position guard
24- route = predictGuardsRoute guard labMap
2525 candidates = filter (/= initialPosition) route
2626
2727 return $
2828 length $
2929 filter (hasLoop guard) $
3030 map (\ pos -> M. insert pos ' #' labMap) candidates
31+ where
32+ hasLoop initialGuard labMap = case predictGuardsRoute initialGuard labMap of
33+ Left InfiniteLoopError -> True
34+ _ -> False
3135
3236-- Laboratory Map
3337type LabMap = Matrix Char
3438
35- data FoldLabMapResult a = Success a | InfiniteLoopError
36-
3739parseLabMap :: String -> LabMap
3840parseLabMap = M. buildMatrix . lines
3941
@@ -50,18 +52,18 @@ findGuard matrix =
5052 [_, _, _, Just pos] -> Right (Guard pos G. Left )
5153 _ -> Left GuardNotFoundError
5254
53- foldLabMapWithGuard :: a -> ( Guard -> a -> a ) -> Guard -> LabMap -> FoldLabMapResult a
54- foldLabMapWithGuard initialValue f initialGuard labMap = go initialGuard HashSet. empty initialValue
55+ predictGuardsRoute :: Guard -> LabMap -> Either Error [ Position ]
56+ predictGuardsRoute initialGuard labMap = go initialGuard HashSet. empty HashSet. empty
5557 where
5658 go guard visited acc =
5759 let guard' = moveGuard guard
58- acc' = f guard acc
60+ acc' = HashSet. insert (position guard) acc
5961 visited' = HashSet. insert guard visited
6062 in if HashSet. member guard visited
61- then InfiniteLoopError
63+ then Left InfiniteLoopError
6264 else
6365 if guard == guard'
64- then Success acc'
66+ then Right ( HashSet. toList acc')
6567 else go guard' visited' acc'
6668
6769 moveGuard :: Guard -> Guard
@@ -72,13 +74,3 @@ foldLabMapWithGuard initialValue f initialGuard labMap = go initialGuard HashSet
7274 Nothing -> guard
7375 Just ' #' -> G. turnRight guard
7476 Just _ -> guard'
75-
76- hasLoop :: Guard -> LabMap -> Bool
77- hasLoop initialGuard labMap = case foldLabMapWithGuard [] (\ _ _ -> [] ) initialGuard labMap of
78- InfiniteLoopError -> True
79- _ -> False
80-
81- predictGuardsRoute :: Guard -> LabMap -> [Position ]
82- predictGuardsRoute guard labMap = case foldLabMapWithGuard HashSet. empty (HashSet. insert . position) guard labMap of
83- InfiniteLoopError -> []
84- Success set -> HashSet. toList set
0 commit comments