X-Git-Url: https://git.njae.me.uk/?p=advent-of-code-19.git;a=blobdiff_plain;f=advent03%2Fsrc%2Fadvent03.hs;h=2d1eef51f4e7d82af73fa819613adfefc184abfc;hp=a541f23b926d4c26edb315041ebf226db60c7473;hb=34400b8723ff60b5dc41593f273fcf6f45664363;hpb=9ae9e4b2751996170400ddea8503a3b0313e724c diff --git a/advent03/src/advent03.hs b/advent03/src/advent03.hs index a541f23..2d1eef5 100644 --- a/advent03/src/advent03.hs +++ b/advent03/src/advent03.hs @@ -1,6 +1,3 @@ --- Some code taken from [AoC 2017 day 5](https://adventofcode.com/2017/day/5), --- and some from [AoC 2018 day 21](https://adventofcode.com/2018/day/21) - import Data.Text (Text) import qualified Data.Text.IO as TIO @@ -13,6 +10,8 @@ import qualified Control.Applicative as CA import Data.List (foldl') import qualified Data.Set as S +import qualified Data.Map as M +import Data.Map ((!)) import Linear (V2(..), (^+^), (^-^), (*^), (*^)) @@ -22,8 +21,11 @@ type Location = V2 Int -- x, y type Visited = S.Set Location -data Path = Path { _visited :: Visited +type TrackedVisited = M.Map Location Int + +data Path = Path { _visited :: TrackedVisited , _tip :: Location + , _currentLength :: Int } deriving (Show, Eq) @@ -36,38 +38,53 @@ main :: IO () main = do text <- TIO.readFile "data/advent03.txt" let segmentss = successfulParse text - print segmentss + let paths = travelAllPaths segmentss -- print $ travelPath $ head segmentss - print $ part1 segmentss - -- print $ part2 machine + print $ part1 paths + print $ part2 paths + +part1 :: [Path] -> Int +part1 paths = closest $ crossovers paths + +part2 :: [Path] -> Int +part2 paths = shortestPaths paths $ crossovers paths -part1 :: [[Segment]] -> Int -part1 segmentss = closest $ crossovers $ travelAllPaths segmentss closest :: Visited -> Int closest points = S.findMin $ S.map manhattan points + +shortestPaths :: [Path] -> Visited -> Int +shortestPaths paths crossings = minimum $ S.map crossingPathLengths crossings + where crossingPathLengths crossing = sum $ map (\p -> (_visited p)!crossing) paths + + crossovers :: [Path] -> Visited crossovers travelledPaths = foldl' S.intersection - (_visited $ head travelledPaths) - (map _visited $ drop 1 travelledPaths) + (M.keysSet $ _visited $ head travelledPaths) + (map (M.keysSet . _visited) $ drop 1 travelledPaths) travelAllPaths :: [[Segment]] -> [Path] travelAllPaths = map travelPath travelPath :: [Segment] -> Path travelPath segments = foldl' travelSegment path0 segments - where path0 = Path { _visited = S.empty, _tip = V2 0 0 } + where path0 = Path { _visited = M.empty, _tip = V2 0 0, _currentLength = 0 } travelSegment :: Path -> Segment -> Path -travelSegment path segment = path { _tip = tip', _visited = visited' } +travelSegment path segment = path { _tip = tip', _visited = visited', _currentLength = len'} where delta = facing $ _direction segment distance = _steps segment start = _tip path + len = _currentLength path + len' = len + distance visited = _visited path - visited' = foldl' (flip S.insert) visited $ take distance $ drop 1 $ iterate (^+^ delta) start + visited' = foldl' insertStep visited $ take distance $ drop 1 $ zip [len, (len + 1) ..] $ iterate (^+^ delta) start tip' = start ^+^ distance *^ delta + insertStep visits (dist, loc) = if loc `M.member` visits + then visits + else M.insert loc dist visits facing :: Direction -> Location facing East = V2 1 0