Lukas Angerer vor 2 Jahren
Ursprung
Commit
c420e13ad1
2 geänderte Dateien mit 184 neuen und 15 gelöschten Zeilen
  1. 179 14
      Day14/BoulderMap.cs
  2. 5 1
      Day14/Program.cs

+ 179 - 14
Day14/BoulderMap.cs

@@ -1,45 +1,210 @@
-namespace Day14;
+using System.Text;
+
+namespace Day14;
 
 public class BoulderMap
 {
     private readonly char[][] _lines;
+    private readonly IAxis _north;
+    private readonly IAxis _east;
+    private readonly IAxis _south;
+    private readonly IAxis _west;
+    private readonly Dictionary<string, int> _keyMap = new Dictionary<string, int>();
 
     public BoulderMap(IList<string> lines)
     {
         _lines = lines.Select(l => l.ToCharArray()).ToArray();
+        _north = new NorthSouth(_lines, 1);
+        _east = new EastWest(_lines, -1);
+        _south = new NorthSouth(_lines, -1);
+        _west = new EastWest(_lines, 1);
     }
 
     public int CalculateMaxNorthLoad()
+    {
+        return CalculateDirectionalLoad(_north);
+    }
+    
+    private int CalculateDirectionalLoad(IAxis axis)
     {
         var load = 0;
-        for (var x = 0; x < _lines[0].Length; x++)
+        foreach (var s in axis.SecondaryRange)
         {
-            var freeY = 0;
-            for (var y = 0; y < _lines.Length; y++)
+            var free = axis.PrimaryRange.First();
+            foreach (var p in axis.PrimaryRange)
             {
-                switch (_lines[y][x])
+                switch (axis.Get(p, s))
                 {
                     case 'O':
-                        if (y != freeY)
+                        if (p != free)
                         {
-                            _lines[y][x] = _lines[freeY][x];
-                            _lines[freeY][x] = 'O';
+                            axis.Swap(p, free, s);
                         }
-                        load += _lines.Length - freeY;
-                        freeY++;
+                        load += axis.NorthLoad(free, s);
+                        free += axis.Delta;
                         break;
                     case '#':
-                        freeY = y + 1;
+                        free = p + axis.Delta;
                         break;
                 }
             }
         }
 
-        foreach (var l in _lines)
+        // foreach (var l in _lines)
+        // {
+        //     Console.WriteLine(l);
+        // }
+        // Console.WriteLine();
+
+        return load;
+    }
+
+    public int Cycle(int n)
+    {
+        var loads = new List<int>();
+        for (var i = 1; i <= n; i++)
         {
-            Console.WriteLine(l);
+            CalculateDirectionalLoad(_north);
+            CalculateDirectionalLoad(_west);
+            CalculateDirectionalLoad(_south);
+            loads.Add(CalculateDirectionalLoad(_east));
+
+            var key = GetKey();
+            Console.WriteLine($"Key: {key} => {loads.Last()}");
+            if (_keyMap.TryGetValue(key, out int value))
+            {
+                Console.WriteLine($"CYCLE: @{i} from {value}");
+                var offset = value;
+                var cycle = i - value;
+                var remainder = (1000000000 - offset) % cycle;
+                return loads[loads.Count - (cycle - remainder) - 1];
+            }
+
+            _keyMap[key] = i;
         }
 
-        return load;
+        return -1;
+    }
+
+    private string GetKey()
+    {
+        var result = new StringBuilder();
+        var start = 0;
+        var run = 0;
+        for (var y = 0; y < _lines.Length; y++)
+        {
+            for (var x = 0; x < _lines[0].Length; x++)
+            {
+                if (_lines[y][x] == 'O')
+                {
+                    run++;
+                }
+                else
+                {
+                    if (run > 0)
+                    {
+                        result.Append(start);
+                        result.Append(':');
+                        result.Append(run);
+                        result.Append('|');
+                        run = 0;
+                    }
+                    start = y * _lines[0].Length + x;
+                }
+            }
+        }
+        
+        if (run > 0)
+        {
+            result.Append(start);
+            result.Append(':');
+            result.Append(run);
+            result.Append('|');
+        }
+
+        return result.ToString();
+    }
+
+    private interface IAxis
+    {
+        int Delta { get; }
+        List<int> PrimaryRange { get; }
+        List<int> SecondaryRange { get; }
+
+        char Get(int primary, int secondary);
+        void Swap(int primaryA, int primaryB, int secondary);
+        int NorthLoad(int primary, int secondary);
+    }
+
+    private class NorthSouth : IAxis
+    {
+        private readonly char[][] _lines;
+        
+        public int Delta { get; }
+        public List<int> PrimaryRange { get; }
+        public List<int> SecondaryRange { get; }
+
+        public NorthSouth(char[][] lines, int delta)
+        {
+            Delta = delta;
+            _lines = lines;
+            PrimaryRange = Enumerable.Range(0, _lines.Length).ToList();
+            if (delta < 0)
+            {
+                PrimaryRange.Reverse();
+            }
+            SecondaryRange = Enumerable.Range(0, _lines[0].Length).ToList();
+        }
+
+        public char Get(int primary, int secondary)
+        {
+            return _lines[primary][secondary];
+        }
+
+        public void Swap(int primaryA, int primaryB, int secondary)
+        {
+            (_lines[primaryA][secondary], _lines[primaryB][secondary]) = (_lines[primaryB][secondary], _lines[primaryA][secondary]);
+        }
+
+        public int NorthLoad(int primary, int secondary)
+        {
+            return Delta > 0 ? PrimaryRange.Count - primary : primary;
+        }
+    }
+    
+    private class EastWest : IAxis
+    {
+        private readonly char[][] _lines;
+        
+        public int Delta { get; }
+        public List<int> PrimaryRange { get; }
+        public List<int> SecondaryRange { get; }
+
+        public EastWest(char[][] lines, int delta)
+        {
+            Delta = delta;
+            _lines = lines;
+            PrimaryRange = Enumerable.Range(0, _lines[0].Length).ToList();
+            if (delta < 0)
+            {
+                PrimaryRange.Reverse();
+            }
+            SecondaryRange = Enumerable.Range(0, _lines.Length).ToList();
+        }
+
+        public char Get(int primary, int secondary)
+        {
+            return _lines[secondary][primary];
+        }
+
+        public void Swap(int primaryA, int primaryB, int secondary)
+        {
+            (_lines[secondary][primaryA], _lines[secondary][primaryB]) = (_lines[secondary][primaryB], _lines[secondary][primaryA]);
+        }
+        
+        public int NorthLoad(int primary, int secondary)
+        {
+            return SecondaryRange.Count - secondary;
+        }
     }
 }

+ 5 - 1
Day14/Program.cs

@@ -19,7 +19,11 @@ var parser = new Parser();
 var boulderMap = parser.Parse(inputFile);
 
 var load = boulderMap.CalculateMaxNorthLoad();
+Console.WriteLine($"North Load: {load}");
 Console.WriteLine();
-Console.WriteLine($"Max North Load: {load}");
+
+load = boulderMap.Cycle(10000);
+Console.WriteLine();
+Console.WriteLine($"== North Load: {load}");
 
 return 0;