@@ -59,3 +59,11 @@ executable day5
 | 
				
			|||||||
  build-depends:
 | 
					  build-depends:
 | 
				
			||||||
    , containers
 | 
					    , containers
 | 
				
			||||||
    , libaoc
 | 
					    , libaoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					executable day6
 | 
				
			||||||
 | 
					  import:         common
 | 
				
			||||||
 | 
					  hs-source-dirs: src
 | 
				
			||||||
 | 
					  main-is:        Day6.hs
 | 
				
			||||||
 | 
					  build-depends:
 | 
				
			||||||
 | 
					    , containers
 | 
				
			||||||
 | 
					    , libaoc
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										77
									
								
								src/Day6.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/Day6.hs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					module Main where
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import qualified Data.Set as S
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Grid = [[Char]]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Dimensions = (Int, Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Coord = (Int, Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data Dir = North | East | South | West deriving (Ord, Eq, Show)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type State = (Coord, Dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					next :: Dir -> Coord -> Coord
 | 
				
			||||||
 | 
					next North (x, y) = (x, y - 1)
 | 
				
			||||||
 | 
					next East (x, y) = (x + 1, y)
 | 
				
			||||||
 | 
					next South (x, y) = (x, y + 1)
 | 
				
			||||||
 | 
					next West (x, y) = (x - 1, y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rotate :: Dir -> Dir
 | 
				
			||||||
 | 
					rotate North = East
 | 
				
			||||||
 | 
					rotate East = South
 | 
				
			||||||
 | 
					rotate South = West
 | 
				
			||||||
 | 
					rotate West = North
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					getPath :: S.Set Coord -> Dimensions -> Coord -> S.Set Coord
 | 
				
			||||||
 | 
					getPath obs (m, n) start = go S.empty start North
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    oob :: Coord -> Bool
 | 
				
			||||||
 | 
					    oob (x, y) = x < 0 || y < 0 || x >= m || y >= n
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    go :: S.Set Coord -> Coord -> Dir -> S.Set Coord
 | 
				
			||||||
 | 
					    go path c d
 | 
				
			||||||
 | 
					      | oob n = S.insert c path
 | 
				
			||||||
 | 
					      | n `S.member` obs = go path c (rotate d)
 | 
				
			||||||
 | 
					      | otherwise = go (S.insert c path) n d
 | 
				
			||||||
 | 
					      where
 | 
				
			||||||
 | 
					        n = next d c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					isLoop :: S.Set Coord -> Dimensions -> Coord -> Bool
 | 
				
			||||||
 | 
					isLoop obs (m, n) start = go S.empty start North
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    oob :: Coord -> Bool
 | 
				
			||||||
 | 
					    oob (x, y) = x < 0 || y < 0 || x >= m || y >= n
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    go :: S.Set State -> Coord -> Dir -> Bool
 | 
				
			||||||
 | 
					    go states c d
 | 
				
			||||||
 | 
					      | oob n = False
 | 
				
			||||||
 | 
					      | (c, d) `S.member` states = True
 | 
				
			||||||
 | 
					      | n `S.member` obs = go states c (rotate d)
 | 
				
			||||||
 | 
					      | otherwise = go (S.insert (c, d) states) n d
 | 
				
			||||||
 | 
					      where
 | 
				
			||||||
 | 
					        n = next d c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main :: IO ()
 | 
				
			||||||
 | 
					main =
 | 
				
			||||||
 | 
					  do
 | 
				
			||||||
 | 
					    grid <- lines <$> readFile "./inputs/day6.in"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let m = length grid
 | 
				
			||||||
 | 
					        n = length $ head grid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let grid' = [((x, y), ch) | (y, row) <- zip [0 ..] grid, (x, ch) <- zip [0 ..] row]
 | 
				
			||||||
 | 
					        obstacles = S.fromList [coord | (coord, ch) <- grid', ch == '#']
 | 
				
			||||||
 | 
					        start = head [coord | (coord, ch) <- grid', ch == '^']
 | 
				
			||||||
 | 
					        path = getPath obstacles (m, n) start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let part1 = S.size path
 | 
				
			||||||
 | 
					        part2 =
 | 
				
			||||||
 | 
					          S.size $
 | 
				
			||||||
 | 
					            S.filter
 | 
				
			||||||
 | 
					              (\p -> isLoop (S.insert p obstacles) (m, n) start)
 | 
				
			||||||
 | 
					              (S.delete start path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    putStr "Part 1: " >> print part1
 | 
				
			||||||
 | 
					    putStr "Part 2: " >> print part2
 | 
				
			||||||
		Reference in New Issue
	
	Block a user