From ed3d8a86cac30561e16c5d68f5342fc47e8e7b30 Mon Sep 17 00:00:00 2001
From: Nathan McCarty <thatonelutenist@stranger.systems>
Date: Sun, 19 Jan 2025 18:46:24 -0500
Subject: [PATCH] Year 2015 Day 9 Part 2

---
 src/Years/Y2015/Day9.md | 52 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 8 deletions(-)

diff --git a/src/Years/Y2015/Day9.md b/src/Years/Y2015/Day9.md
index acb702c..8abf4b2 100644
--- a/src/Years/Y2015/Day9.md
+++ b/src/Years/Y2015/Day9.md
@@ -210,11 +210,9 @@ lengths.
 
 ```idris
 shortestPath : Has (Reader DistanceMap) fs => Has (Except String) fs =>
-  (paths : List (List Location)) -> Eff fs (List Location, Integer)
+  (paths : List (List Location, Integer)) -> Eff fs (List Location, Integer)
 shortestPath paths = do
-  lens <- traverse pathLen paths
-  let pairs = zip paths lens
-  shortest pairs Nothing
+  shortest paths Nothing
   where
     shortest : List (a, Integer) -> (acc : Maybe (a, Integer)) 
       -> Eff fs (a, Integer)
@@ -228,6 +226,27 @@ shortestPath paths = do
             else shortest xs (Just y)
 ```
 
+Calculate the longest path from a list of paths by recursively comparing
+lengths.
+
+```idris
+longestPath : Has (Reader DistanceMap) fs => Has (Except String) fs =>
+  (paths : List (List Location, Integer)) -> Eff fs (List Location, Integer)
+longestPath paths = do
+  longest paths Nothing
+  where
+    longest : List (a, Integer) -> (acc : Maybe (a, Integer)) 
+      -> Eff fs (a, Integer)
+    longest [] acc = note "No paths" acc
+    longest (x :: xs) acc = 
+      case acc of
+        Nothing => longest xs (Just x)
+        Just y => 
+          if (snd x) > (snd y)
+            then longest xs (Just x)
+            else longest xs (Just y)
+```
+
 ## Part Functions
 
 ### Part 1
@@ -236,7 +255,8 @@ Parse our locations, turn them into a `DistanceMap`, load that into our reader,
 generate our paths, then find the one with the shortest length.
 
 ```idris
-part1 : Eff (PartEff String) (Integer, ())
+part1 : 
+  Eff (PartEff String) (Integer, (DistanceMap, List (List Location, Integer)))
 part1 = do
   locations <- map lines (askAt "input") >>= traverse parseLocationPair
   info "Locations: \{show locations}"
@@ -246,13 +266,29 @@ part1 = do
   paths <- map Prelude.toList allPaths
   trace "Paths: \{show paths}"
   info "Found \{show $ length paths} paths"
-  (path, len) <- shortestPath paths
+  distances <- traverse pathLen paths
+  let pairs = zip paths distances
+  (path, len) <- shortestPath pairs
   info "Shortest Path: \{show path} \{show len}"
-  pure (len, ())
+  pure (len, (distance_map, pairs))
+```
+
+### Part 2
+
+Feed the locations back into a longest path function
+
+```idris
+part2 : (DistanceMap, List (List Location, Integer))
+  -> Eff (PartEff String) Integer
+part2 (distance_map, pairs) = do
+  runReader distance_map {fs = Reader DistanceMap :: PartEff String} $ do
+  (path, len) <- longestPath pairs
+  info "Longest Path: \{show path} \{show len}"
+  pure len
 ```
 
 <!-- idris
 public export
 day9 : Day
-day9 = First 9 part1
+day9 = Both 9 part1 part2
 -->