@@ -11,10 +11,24 @@ data Error = GuardNotFoundError
1111 deriving (Eq , Show )
1212
1313partOne :: String -> Either Error Int
14- partOne input = length <$> predictGuardsRoute (parseLabMap input)
14+ partOne input = do
15+ let labMap = parseLabMap input
16+ guard <- findGuard labMap
17+ let route = predictGuardsRoute guard labMap
18+ return (length route)
1519
1620partTwo :: String -> Either Error Int
17- partTwo _input = Right 0
21+ partTwo input = do
22+ let labMap = parseLabMap input
23+ guard <- findGuard labMap
24+ let initialPosition = position guard
25+ route = predictGuardsRoute guard labMap
26+ candidates = filter (/= initialPosition) route
27+
28+ return $
29+ length $
30+ filter (hasLoop guard) $
31+ map (\ pos -> M. insert pos ' #' labMap) candidates
1832
1933-- Laboratory Map
2034type LabMap = Matrix Char
@@ -37,26 +51,33 @@ findGuard matrix =
3751 [_, _, _, Just pos] -> Right (Guard pos G. Left )
3852 _ -> Left GuardNotFoundError
3953
40- predictGuardsRoute :: LabMap -> Either Error [Position ]
41- predictGuardsRoute labMap = do
42- guard <- findGuard labMap
43- return $ go guard HashSet. empty HashSet. empty
54+ hasLoop :: Guard -> LabMap -> Bool
55+ hasLoop initialGuard labMap = go initialGuard HashSet. empty
56+ where
57+ go :: Guard -> Visited -> Bool
58+ go guard visited =
59+ let guard' = moveGuard guard labMap
60+ visited' = HashSet. insert guard visited
61+ in HashSet. member guard visited || ((guard /= guard') && go guard' visited')
62+
63+ predictGuardsRoute :: Guard -> LabMap -> [Position ]
64+ predictGuardsRoute initialGuard labMap = go initialGuard HashSet. empty HashSet. empty
4465 where
4566 go :: Guard -> Visited -> HashSet Position -> [Position ]
4667 go guard visited acc =
47- let guard' = moveGuard guard
68+ let guard' = moveGuard guard labMap
4869 acc' = HashSet. insert (position guard) acc
4970 visited' = HashSet. insert guard visited
5071 in -- If we have hit a loop or if the guard can't move anymore, finish prediction
51- if HashSet. member guard visited || ( guard == guard')
72+ if HashSet. member guard visited || guard == guard'
5273 then HashSet. toList acc'
5374 else go guard' visited' acc'
5475
55- moveGuard :: Guard -> Guard
56- moveGuard guard =
57- let guard' = G. moveForward guard
58- mObstacle = M. lookup (position guard') labMap
59- in case mObstacle of
60- Nothing -> guard
61- Just ' #' -> G. turnRight guard
62- Just _ -> guard'
76+ moveGuard :: Guard -> LabMap -> Guard
77+ moveGuard guard labMap =
78+ let guard' = G. moveForward guard
79+ mObstacle = M. lookup (position guard') labMap
80+ in case mObstacle of
81+ Nothing -> guard
82+ Just ' #' -> G. turnRight guard
83+ Just _ -> guard'
0 commit comments