diff --git a/Lib.hs b/Lib.hs index 61d97fa..b198b8a 100644 --- a/Lib.hs +++ b/Lib.hs @@ -1,6 +1,7 @@ -module Lib (readFile', split, count, tRead) where +module Lib (readFile', tRead, buildGrid, split, count) where import Data.ByteString qualified as B (readFile) +import Data.Map qualified as M import Data.Text (Text) import Data.Text.Encoding qualified as T (decodeUtf8) import Data.Text.Read qualified as TR @@ -13,6 +14,10 @@ readFile' f = T.decodeUtf8 <$> B.readFile f tRead :: Text -> Int tRead = (\(Right (n, _)) -> n) . TR.signed TR.decimal +-- Data.Map -- +buildGrid :: [[a]] -> M.Map (Int, Int) a +buildGrid xs = M.fromList [((x, y), a) | (row, x) <- zip xs [0 ..], (a, y) <- zip row [0 ..]] + -- Utility -- split :: (Eq a) => a -> [a] -> [[a]] split delimiter list = diff --git a/day10.hs b/day10.hs new file mode 100644 index 0000000..a950948 --- /dev/null +++ b/day10.hs @@ -0,0 +1,48 @@ +import Data.List (find) +import Data.Map qualified as M +import Data.Maybe (catMaybes, isNothing, mapMaybe) +import Data.Set qualified as S +import Lib (buildGrid, readFile') + +data Direction = East | West | North | South deriving (Show, Eq) + +type Coord = (Int, Int) + +main :: IO () +main = do + grid <- buildGrid . lines <$> readFile "day10.in" + let [((sx, sy), _)] = M.toList $ M.filter (== 'S') grid + let path = + head $ + mapMaybe + (uncurry $ travel grid []) + [ ((sx - 1, sy), North), + ((sx, sy + 1), East) + ] + + putStr "Q1: " + print $ div (length path) 2 + + putStr "Q2: " + print $ pick (shoelace path) (length path) + +travel :: M.Map Coord Char -> [Coord] -> Coord -> Direction -> Maybe [Coord] +travel grid a c@(x, y) d + | isNothing (M.lookup c grid) || cur == '.' = Nothing + | cur == 'S' = Just $ c : a + | (cur, d) `elem` [('L', West), ('|', North), ('J', East)] = travel grid (c : a) (x - 1, y) North + | (cur, d) `elem` [('F', West), ('|', South), ('7', East)] = travel grid (c : a) (x + 1, y) South + | (cur, d) `elem` [('L', South), ('-', East), ('F', North)] = travel grid (c : a) (x, y + 1) East + | (cur, d) `elem` [('J', South), ('-', West), ('7', North)] = travel grid (c : a) (x, y - 1) West + where + cur = grid M.! c + +-- https://en.wikipedia.org/wiki/Shoelace_formula +-- this just uses trapezoids/triangles from consecutive points +shoelace :: [Coord] -> Int +shoelace xs = flip div 2 . abs . sum $ zipWith (\(x1, y1) (x2, y2) -> (x1 * y2) - (x2 * y1)) xs (tail $ cycle xs) + +-- https://en.wikipedia.org/wiki/Pick%27s_theorem +-- area -> path length -> integers inside +pick :: Int -> Int -> Int +pick a b = (a + 1) - div b 2