| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- 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;
- foreach (var s in axis.SecondaryRange)
- {
- var free = axis.PrimaryRange.First();
- foreach (var p in axis.PrimaryRange)
- {
- switch (axis.Get(p, s))
- {
- case 'O':
- if (p != free)
- {
- axis.Swap(p, free, s);
- }
- load += axis.NorthLoad(free, s);
- free += axis.Delta;
- break;
- case '#':
- free = p + axis.Delta;
- break;
- }
- }
- }
- // 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++)
- {
- 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 -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;
- }
- }
- }
|