module Commons where import GHC.IO.Handle (isEOF) import Data.Array (Array, listArray, (!), indices) data Direction = North | East | West | South deriving (Eq, Show) data Tile = Ground | Start | Pipe (Direction, Direction) deriving (Eq, Show) type Grid = Array (Int, Int) Tile parseLine :: String -> [Tile] parseLine [] = [] parseLine ('.': t) = Ground: parseLine t parseLine ('S': t) = Start: parseLine t parseLine ('|': t) = Pipe (North, South): parseLine t parseLine ('-': t) = Pipe (East, West): parseLine t parseLine ('L': t) = Pipe (North, East): parseLine t parseLine ('J': t) = Pipe (North, West): parseLine t parseLine ('7': t) = Pipe (South, West): parseLine t parseLine ('F': t) = Pipe (South, East): parseLine t parseGrid :: [[Tile]] -> IO Grid parseGrid otherTiles = do done <- isEOF if done then return $ listArray ((1, 1), (length otherTiles, length (otherTiles !! 1))) $ concat otherTiles else do line <- getLine let tiles = parseLine line parseGrid (otherTiles ++ [tiles]) parse :: IO Grid parse = parseGrid [] findStart :: [(Int, Int)] -> Grid -> (Int, Int) findStart (h: t) grid | grid ! h == Start = h | otherwise = findStart t grid getStartCoordinates :: Grid -> (Int, Int) getStartCoordinates grid = findStart (indices grid) grid getStartDirection :: (Int, Int) -> Grid -> (Direction, (Int, Int)) getStartDirection (y, x) grid | grid ! (y + 1, x) == Pipe (North, South) = (South, (y + 1, x)) | grid ! (y + 1, x) == Pipe (North, East) = (South, (y + 1, x)) | grid ! (y + 1, x) == Pipe (North, West) = (South, (y + 1, x)) | grid ! (y, x + 1) == Pipe (East, West) = (East, (y, x + 1)) | grid ! (y, x + 1) == Pipe (North, West) = (East, (y, x + 1)) | grid ! (y, x + 1) == Pipe (South, West) = (East, (y, x + 1))