Преглед на файлове

Day 23 cleanup of part 1

Lukas Angerer преди 2 години
родител
ревизия
8ba95ebd62
променени са 3 файла, в които са добавени 17 реда и са изтрити 39 реда
  1. 15 36
      Day23/Map.cs
  2. 2 1
      Day23/PathNode.cs
  3. 0 2
      Day23/Tile.cs

+ 15 - 36
Day23/Map.cs

@@ -60,19 +60,7 @@ public class Map
     public void BuildGraph()
     {
         var startTile = At(_start)!;
-        _root = BuildPath(startTile, Neighbors(startTile).Single().Position.Subtract(startTile.Position));
-
-        // Assert that we have no cycles in the graph
-        var seen = new HashSet<PathNode>();
-        foreach (var n in BreadthFirst())
-        {
-            if (seen.Contains(n))
-            {
-                throw new Exception("There is a cycle in the graph");
-            }
-
-            seen.Add(n);
-        }
+        _root = BuildPath(startTile, Neighbors(startTile).Single().Position.Subtract(startTile.Position), new Dictionary<Vec, PathNode>());
     }
     
     public int LongestPath()
@@ -87,12 +75,12 @@ public class Map
             var (current, length) = queue.Dequeue();
             var nextLength = length + current.Tiles.Count + 1;
 
-            if (current.Connected.Count == 0)
+            if (current.Outgoing.Count == 0)
             {
                 longest = int.Max(longest, nextLength);
             }
 
-            foreach (var next in current.Connected)
+            foreach (var next in current.Outgoing)
             {
                 queue.Enqueue((next, nextLength));
             }
@@ -102,20 +90,28 @@ public class Map
         return longest - 2;
     }
 
-    private PathNode BuildPath(Tile start, Vec dir)
+    private PathNode BuildPath(Tile start, Vec dir, IDictionary<Vec, PathNode> map)
     {
+        if (map.TryGetValue(start.Position, out PathNode? path))
+        {
+            return path;
+        }
+        
         var pathNode = new PathNode();
         pathNode.Tiles.AddRange(Follow(start, dir));
+        map[start.Position] = pathNode;
 
-        var crossing = At(pathNode.Tiles.Last().Position.Add(pathNode.Tiles.Last().ArrowDirection()))!;
-        crossing.Incoming.Add(pathNode);
+        var arrowTile = pathNode.Tiles.Last();
+        var crossing = At(arrowTile.Position.Add(arrowTile.ArrowDirection()))!;
 
         if (crossing != At(_goal))
         {
             foreach (var outgoing in Neighbors(crossing)
                          .Where(x => x.Position.Add(x.ArrowDirection()) != crossing.Position))
             {
-                pathNode.Connected.Add(BuildPath(outgoing, outgoing.ArrowDirection()));
+                var outgoingPath = BuildPath(outgoing, outgoing.ArrowDirection(), map);
+                outgoingPath.Incoming.Add(pathNode);
+                pathNode.Outgoing.Add(outgoingPath);
             }
         }
 
@@ -173,21 +169,4 @@ public class Map
 
         yield return current;
     }
-
-    private IEnumerable<PathNode> BreadthFirst()
-    {
-        Assert(_root != null);
-        var queue = new Queue<PathNode>();
-        queue.Enqueue(_root!);
-        while (queue.Count > 0)
-        {
-            var current = queue.Dequeue();
-            yield return current;
-
-            foreach (var next in current.Connected)
-            {
-                queue.Enqueue(next);
-            }
-        }
-    }
 }

+ 2 - 1
Day23/PathNode.cs

@@ -3,5 +3,6 @@
 public class PathNode
 {
     public List<Tile> Tiles { get; } = new List<Tile>();
-    public List<PathNode> Connected { get; } = new List<PathNode>();
+    public List<PathNode> Outgoing { get; } = new List<PathNode>();
+    public List<PathNode> Incoming { get; } = new List<PathNode>();
 }

+ 0 - 2
Day23/Tile.cs

@@ -4,8 +4,6 @@ public class Tile
 {
     public char Value { get; }
     public Vec Position { get; }
-    public IList<PathNode> Incoming { get; } = new List<PathNode>();
-    public IList<PathNode> Outgoing { get; } = new List<PathNode>();
 
     public bool IsPath => Value == '.' || IsArrow;
     public bool IsArrow => Value == '<' || Value == '>' || Value == '^' || Value == 'v';