Done day 3 part 2
[advent-of-code-19.git] / advent03 / src / advent03.hs
index a541f23b926d4c26edb315041ebf226db60c7473..2d1eef51f4e7d82af73fa819613adfefc184abfc 100644 (file)
@@ -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