diff options
Diffstat (limited to 'aoc2019/Day15.cs')
-rw-r--r-- | aoc2019/Day15.cs | 330 |
1 files changed, 156 insertions, 174 deletions
diff --git a/aoc2019/Day15.cs b/aoc2019/Day15.cs index 59d720c..046f52f 100644 --- a/aoc2019/Day15.cs +++ b/aoc2019/Day15.cs @@ -1,224 +1,206 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using aoc2019.lib; +namespace aoc2019; -namespace aoc2019 +public sealed class Day15 : Day { - public sealed class Day15 : Day - { - private readonly bool verbose = false; - private readonly IntCodeVM vm; + private readonly bool verbose = false; + private readonly IntCodeVM vm; - public Day15() : base(15, "Oxygen System") - { - vm = new IntCodeVM(Input.First()); - } + public Day15() : base(15, "Oxygen System") + { + vm = new IntCodeVM(Input.First()); + } - public override string Part1() + public override string Part1() + { + vm.Reset(); + var currentLocation = new Location(0, 0); + var halt = IntCodeVM.HaltType.Waiting; + while (halt == IntCodeVM.HaltType.Waiting) { - vm.Reset(); - var currentLocation = new Location(0, 0); - var halt = IntCodeVM.HaltType.Waiting; - while (halt == IntCodeVM.HaltType.Waiting) + var direction = currentLocation!.NextDirection(); + if (direction <= 4) { - var direction = currentLocation.NextDirection(); - if (direction <= 4) + var (x, y) = currentLocation.Neighbor(direction); + if (Location.GetLocation(x, y) == null) { - var (x, y) = currentLocation.Neighbor(direction); - if (Location.GetLocation(x, y) == null) + halt = vm.Run(direction); + currentLocation = vm.Result switch { - halt = vm.Run(direction); - switch (vm.Result) - { - case Location.Wall: - new Location(x, y, Location.Opposites[direction], Location.Wall); - break; - case Location.Empty: - currentLocation = new Location(x, y, Location.Opposites[direction]); - break; - case Location.System: - currentLocation = new Location(x, y, Location.Opposites[direction], Location.System); - break; - default: - throw new Exception($"Unknown IntCodeVM response: {vm.Result}"); - } - } + Location.Wall => new Location(x, y, Location.Opposites[direction], Location.Wall), + Location.Empty => new Location(x, y, Location.Opposites[direction]), + Location.System => new Location(x, y, Location.Opposites[direction], Location.System), + _ => throw new Exception($"Unknown IntCodeVM response: {vm.Result}"), + }; } - else + } + else + { + direction = currentLocation.PreviousDirection; + if (direction > 0) { - direction = currentLocation.PreviousDirection; - if (direction > 0) + halt = vm.Run(direction); + currentLocation = vm.Result switch { - halt = vm.Run(direction); - switch (vm.Result) - { - case Location.Empty: - case Location.System: - currentLocation = Location.GetLocation(currentLocation.Neighbor(direction)); - break; - default: - throw new Exception($"Unknown or unexpected response for previous room: {vm.Result}"); - } - } - else + Location.Empty or Location.System => Location.GetLocation(currentLocation.Neighbor(direction)), + _ => throw new Exception($"Unknown or unexpected response for previous room: {vm.Result}"), + }; + } + else + { + if (verbose) { - if (verbose) + // find extents of canvas + int xMin, xMax, yMin, yMax; + xMin = yMin = int.MaxValue; + xMax = yMax = int.MinValue; + foreach (var (x, y) in Location.AllLocations.Keys) { - // find extents of canvas - int xMin, xMax, yMin, yMax; - xMin = yMin = int.MaxValue; - xMax = yMax = int.MinValue; - foreach (var (x, y) in Location.AllLocations.Keys) - { - if (x < xMin) xMin = x; - if (x > xMax) xMax = x; - if (y < yMin) yMin = y; - if (y > yMax) yMax = y; - } - - Console.WriteLine($"Canvas extends from ({xMin}, {yMin}) to ({xMax}, {yMax})"); - - // print board - for (var y = yMin; y <= yMax; y++) - { - var line = ""; - for (var x = xMin; x <= xMax; x++) - if (Location.AllLocations.ContainsKey((x, y))) - line += Location.AllLocations[(x, y)].Image(); - else - line += "@"; - - Console.WriteLine(line); - } + if (x < xMin) xMin = x; + if (x > xMax) xMax = x; + if (y < yMin) yMin = y; + if (y > yMax) yMax = y; } - currentLocation = Location.OxygenLocation; - var distance = 0; - while (currentLocation.PreviousDirection != 0) + Console.WriteLine($"Canvas extends from ({xMin}, {yMin}) to ({xMax}, {yMax})"); + + // print board + for (var y = yMin; y <= yMax; y++) { - distance++; - currentLocation = Location.GetLocation(currentLocation.PreviousLocation()); + var line = ""; + for (var x = xMin; x <= xMax; x++) + if (Location.AllLocations.ContainsKey((x, y))) + line += Location.AllLocations[(x, y)].Image(); + else + line += "@"; + + Console.WriteLine(line); } + } - return $"{distance}"; + currentLocation = Location.OxygenLocation; + var distance = 0; + while (currentLocation?.PreviousDirection != 0) + { + distance++; + currentLocation = Location.GetLocation(currentLocation!.PreviousLocation()); } + + return $"{distance}"; } } - - return ""; } - public override string Part2() - { - var changed = true; - while (changed) - { - changed = false; - foreach (var location in Location.AllLocations.Values) - changed = location.UpdateDistanceToOxygenSystem() || changed; - } + return ""; + } - return Location.AllLocations.Values - .Where(l => !l.IsWall) - .Max(l => l.DistanceToOxygenSystem) - .ToString(); + public override string Part2() + { + var changed = true; + while (changed) + { + changed = false; + foreach (var location in Location.AllLocations.Values) + changed = location.UpdateDistanceToOxygenSystem() || changed; } - private class Location - { - public const int Wall = 0; - public const int Empty = 1; - public const int System = 2; + return Location.AllLocations.Values + .Where(l => !l.IsWall) + .Max(l => l.DistanceToOxygenSystem) + .ToString(); + } - private static readonly int[] Dx = {0, 0, 0, 1, -1}; - private static readonly int[] Dy = {0, 1, -1, 0, 0}; - public static readonly int[] Opposites = {0, 2, 1, 4, 3}; + private class Location + { + public const int Wall = 0; + public const int Empty = 1; + public const int System = 2; - public static readonly Dictionary<(int x, int y), Location> - AllLocations = new Dictionary<(int x, int y), Location>(); + private static readonly int[] Dx = { 0, 0, 0, 1, -1 }; + private static readonly int[] Dy = { 0, 1, -1, 0, 0 }; + public static readonly int[] Opposites = { 0, 2, 1, 4, 3 }; - private readonly int currentType; - public int DistanceToOxygenSystem = int.MaxValue - 1; + public static readonly Dictionary<(int x, int y), Location> AllLocations = new(); - private int searchDirection = 1; + private readonly int currentType; + public int DistanceToOxygenSystem = int.MaxValue - 1; - public Location(int x, int y, int prev = 0, int type = Empty) - { - PreviousDirection = prev; - currentType = type; - X = x; - Y = y; + private int searchDirection = 1; - if (type == System) - { - OxygenLocation = this; - DistanceToOxygenSystem = 0; - // Console.WriteLine($"Found Oxygen System at ({x}, {y})"); - } + public Location(int x, int y, int prev = 0, int type = Empty) + { + PreviousDirection = prev; + currentType = type; + X = x; + Y = y; - AllLocations.Add((x, y), this); + if (type == System) + { + OxygenLocation = this; + DistanceToOxygenSystem = 0; + // Console.WriteLine($"Found Oxygen System at ({x}, {y})"); } - public static Location OxygenLocation { get; private set; } - public int PreviousDirection { get; } - private int X { get; } - private int Y { get; } + AllLocations.Add((x, y), this); + } - public bool IsWall => currentType == Wall; + public static Location? OxygenLocation { get; private set; } + public int PreviousDirection { get; } + private int X { get; } + private int Y { get; } - public string Image() - { - return currentType switch - { - Wall => "\u2587", - Empty => X == 0 && Y == 0 ? "S" : " ", - System => "O", - _ => "?" - }; - } + public bool IsWall => currentType == Wall; - public bool UpdateDistanceToOxygenSystem() + public string Image() + { + return currentType switch { - if (currentType != Empty) return false; + Wall => "\u2587", + Empty => X == 0 && Y == 0 ? "S" : " ", + System => "O", + _ => "?" + }; + } + + public bool UpdateDistanceToOxygenSystem() + { + if (currentType != Empty) return false; - foreach (var direction in Enumerable.Range(1, 4)) + foreach (var direction in Enumerable.Range(1, 4)) + { + var distance = GetLocation(Neighbor(direction))?.DistanceToOxygenSystem ?? int.MaxValue; + if (distance + 1 < DistanceToOxygenSystem) { - var distance = GetLocation(Neighbor(direction))?.DistanceToOxygenSystem ?? int.MaxValue; - if (distance + 1 < DistanceToOxygenSystem) - { - DistanceToOxygenSystem = distance + 1; - return true; - } + DistanceToOxygenSystem = distance + 1; + return true; } - - return false; } - public (int, int) Neighbor(int direction) - { - return (X + Dx[direction], Y + Dy[direction]); - } + return false; + } - public (int, int) PreviousLocation() - { - return Neighbor(PreviousDirection); - } + public (int, int) Neighbor(int direction) + { + return (X + Dx[direction], Y + Dy[direction]); + } - public int NextDirection() - { - return searchDirection++; - } + public (int, int) PreviousLocation() + { + return Neighbor(PreviousDirection); + } - public static Location GetLocation(int x, int y) - { - return AllLocations.ContainsKey((x, y)) ? AllLocations[(x, y)] : null; - } + public int NextDirection() + { + return searchDirection++; + } - public static Location GetLocation((int x, int y) coords) - { - return GetLocation(coords.x, coords.y); - } + public static Location? GetLocation(int x, int y) + { + return AllLocations.ContainsKey((x, y)) ? AllLocations[(x, y)] : null; + } + + public static Location? GetLocation((int x, int y) coords) + { + return GetLocation(coords.x, coords.y); } } -} \ No newline at end of file +} |