@@ -116,3 +116,9 @@ executable day14
 | 
				
			|||||||
  build-depends:
 | 
					  build-depends:
 | 
				
			||||||
    , containers
 | 
					    , containers
 | 
				
			||||||
    , libaoc
 | 
					    , libaoc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					executable day15
 | 
				
			||||||
 | 
					  import:         common
 | 
				
			||||||
 | 
					  hs-source-dirs: src
 | 
				
			||||||
 | 
					  main-is:        Day15.hs
 | 
				
			||||||
 | 
					  build-depends:  containers
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										75
									
								
								src/Day15.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								src/Day15.hs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					module Main where
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import qualified Data.Map as M
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Coord = (Int, Int)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Grid = M.Map Coord Char
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					data Dir = East | West | North | South deriving (Eq)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					next :: Coord -> Dir -> Coord
 | 
				
			||||||
 | 
					next (x, y) East = (x + 1, y)
 | 
				
			||||||
 | 
					next (x, y) West = (x - 1, y)
 | 
				
			||||||
 | 
					next (x, y) North = (x, y - 1)
 | 
				
			||||||
 | 
					next (x, y) South = (x, y + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dir :: Char -> Dir
 | 
				
			||||||
 | 
					dir '>' = East
 | 
				
			||||||
 | 
					dir '<' = West
 | 
				
			||||||
 | 
					dir '^' = North
 | 
				
			||||||
 | 
					dir 'v' = South
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					widen :: Char -> [Char]
 | 
				
			||||||
 | 
					widen '#' = "##"
 | 
				
			||||||
 | 
					widen 'O' = "[]"
 | 
				
			||||||
 | 
					widen '.' = ".."
 | 
				
			||||||
 | 
					widen '@' = "@."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					parse :: [[Char]] -> (Coord, Grid)
 | 
				
			||||||
 | 
					parse raw =
 | 
				
			||||||
 | 
					  let [bot] = [(x, y) | (y, row) <- zip [0 ..] raw, (x, ch) <- zip [0 ..] row, ch == '@']
 | 
				
			||||||
 | 
					      raw' = [((x, y), ch) | (y, row) <- zip [0 ..] raw, (x, ch) <- zip [0 ..] row]
 | 
				
			||||||
 | 
					      grid = M.insert bot '.' $ M.fromList raw'
 | 
				
			||||||
 | 
					   in (bot, grid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					move :: [Dir] -> Coord -> Grid -> Grid
 | 
				
			||||||
 | 
					move [] _ grid = grid
 | 
				
			||||||
 | 
					move (d : ds) c grid = case move' c d grid of
 | 
				
			||||||
 | 
					  Nothing -> move ds c grid
 | 
				
			||||||
 | 
					  Just grid' -> move ds (next c d) grid'
 | 
				
			||||||
 | 
					  where
 | 
				
			||||||
 | 
					    move' :: Coord -> Dir -> Grid -> Maybe Grid
 | 
				
			||||||
 | 
					    move' c d grid = case M.lookup n grid of
 | 
				
			||||||
 | 
					      Just '.' -> Just grid
 | 
				
			||||||
 | 
					      Just '#' -> Nothing
 | 
				
			||||||
 | 
					      Just 'O' -> push n d <$> move' n d grid
 | 
				
			||||||
 | 
					      Just '[' | d `elem` [East, West] -> push n d <$> move' n d grid
 | 
				
			||||||
 | 
					      Just '[' -> push n d . push r d <$> (move' n d grid >>= move' r d)
 | 
				
			||||||
 | 
					      Just ']' | d `elem` [East, West] -> push n d <$> move' n d grid
 | 
				
			||||||
 | 
					      Just ']' -> push n d . push l d <$> (move' n d grid >>= move' l d)
 | 
				
			||||||
 | 
					      _ -> error "what?"
 | 
				
			||||||
 | 
					      where
 | 
				
			||||||
 | 
					        n :: Coord
 | 
				
			||||||
 | 
					        n@(x, y) = next c d
 | 
				
			||||||
 | 
					        r = (x + 1, y)
 | 
				
			||||||
 | 
					        l = (x - 1, y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        push :: Coord -> Dir -> Grid -> Grid
 | 
				
			||||||
 | 
					        push c d grid = case M.lookup c grid of
 | 
				
			||||||
 | 
					          Just ch -> M.insert (next c d) ch $ M.insert c '.' grid
 | 
				
			||||||
 | 
					          Nothing -> error "what?"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gps :: Grid -> Char -> Int
 | 
				
			||||||
 | 
					gps grid char = sum [y * 100 + x | ((x, y), ch) <- M.assocs grid, ch == char]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					main :: IO ()
 | 
				
			||||||
 | 
					main =
 | 
				
			||||||
 | 
					  do
 | 
				
			||||||
 | 
					    (raw, map dir . concat -> moves) <- break null . lines <$> readFile "./inputs/day15.in"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let (bot1, grid1) = parse raw
 | 
				
			||||||
 | 
					        (bot2, grid2) = parse . map (concatMap widen) $ raw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    putStr "Part 1: " >> print (gps (move moves bot1 grid1) 'O')
 | 
				
			||||||
 | 
					    putStr "Part 2: " >> print (gps (move moves bot2 grid2) '[')
 | 
				
			||||||
		Reference in New Issue
	
	Block a user