import Data.List import Data.List.Split import Flow main :: IO () main = do inputText <- getContents let input = parseInput inputText putStr "Part 1: " putStrLn $ part1 input --putStrLn $ show $ growBoard (-5, -6) $ growBoard (5, 6) emptyBoard part1 :: ([Dir], [Dir]) -> String part1 _ = " " parseInput :: String -> ([Dir], [Dir]) parseInput input = (wires1, wires2) where wires1:wires2:_ = input |> lines |> map (splitOn "," .> map parseDir) type Mat = [[Bool]] data Board = Board { mat :: Mat , pos :: (Int, Int) , origin :: (Int, Int) } emptyBoard :: Board emptyBoard = Board {mat = [], pos = (0, 0), origin = (0, 0)} ensureBoardPos :: (Int, Int) -> Board -> Board ensureBoardPos _ board = board growBoard :: (Int, Int) -> Board -> Board growBoard (x, y) board = growBoardX x (growBoardY y board) growBoardY :: Int -> Board -> Board growBoardY 0 board = board growBoardY y board = do let incY (x0, y0) = (x0, y0 + abs y) let newBoard = mapBoardMat (growMatY y) board if y < 0 then mapBoardPos incY $ mapBoardOrigin incY newBoard else newBoard growBoardX :: Int -> Board -> Board growBoardX 0 board = board growBoardX x board = do let incX (x0, y0) = (x0 + abs x, y0) let newBoard = mapBoardMat (growMatX x) board if x < 0 then mapBoardPos incX $ mapBoardOrigin incX newBoard else newBoard mapBoardMat :: (Mat -> Mat) -> Board -> Board mapBoardMat mapping board = Board { mat = withBoardMat mapping board , pos = (pos board) , origin = (origin board) } withBoardMat :: (Mat -> a) -> Board -> a withBoardMat mapping board = (mapping (mat board)) mapBoardOrigin :: ((Int, Int) -> (Int, Int)) -> Board -> Board mapBoardOrigin mapping board = Board {mat = mat board, pos = pos board, origin = mapping (origin board)} withBoardOrigin :: ((Int, Int) -> a) -> Board -> a withBoardOrigin mapping board = (mapping (origin board)) mapBoardPos :: ((Int, Int) -> (Int, Int)) -> Board -> Board mapBoardPos mapping board = Board {mat = mat board, pos = mapping (pos board), origin = origin board} withBoardPos :: ((Int, Int) -> a) -> Board -> a withBoardPos mapping board = (mapping (pos board)) instance Show Board where show board = concat $ intersperse "\n" [ [boardChar (x, y) board | (x, _) <- zip [0 ..] row] | (y, row) <- zip [0 ..] (mat board) ] boardChar :: (Int, Int) -> Board -> Char boardChar loc board | (origin board) == loc = 'o' | (pos board) == loc = '*' | otherwise = do let (x, y) = loc if (mat board) !! y !! x then '+' else '.' data Dir = Up Int | Dn Int | Lt Int | Rt Int parseDir :: String -> Dir parseDir text = do let n = read $ tail text case text !! 0 of 'U' -> Up n 'D' -> Dn n 'L' -> Lt n 'R' -> Rt n dirMap :: (Int -> Int) -> Dir -> Dir dirMap mapping (Up n) = Up (mapping n) dirMap mapping (Dn n) = Dn (mapping n) dirMap mapping (Lt n) = Lt (mapping n) dirMap mapping (Rt n) = Rt (mapping n) dirMag :: Dir -> Int dirMag (Up n) = n dirMag (Dn n) = n dirMag (Lt n) = n dirMag (Rt n) = n dirPair :: Dir -> (Int, Int) dirPair (Up n) = (0, -n) dirPair (Dn n) = (0, n) dirPair (Lt n) = (-n, 0) dirPair (Rt n) = (n, 0) growMatDir :: Dir -> Mat -> Mat growMatDir dir mat | dirMag dir == 0 = mat | otherwise = growMat (dirPair dir) mat growMat :: (Int, Int) -> Mat -> Mat growMat (x, y) mat = growMatX x (growMatY y mat) growMatX :: Int -> Mat -> Mat growMatX 0 mat = mat growMatX x mat = if x < 0 then [take (abs x) (repeat False) ++ row | row <- mat] else [row ++ take (abs x) (repeat False) | row <- mat] growMatY :: Int -> Mat -> Mat growMatY 0 mat = mat growMatY y mat = if y < 0 then (take (abs y) (repeat (take (matW mat) (repeat False)))) ++ mat else mat ++ (take (abs y) (repeat (take (matW mat) (repeat False)))) matSize :: Mat -> (Int, Int) matSize mat = (matW mat, matH mat) matW :: Mat -> Int matW mat = if matH mat == 0 then 0 else mx (map length mat) matH :: Mat -> Int matH mat = length mat mx :: [Int] -> Int mx [] = 0 mx [x] = x mx (x:xs) | (mx xs) > x = mx xs | otherwise = x