From c5e8ebbf225570eedcb1603eaff6a555bda642ee Mon Sep 17 00:00:00 2001 From: Stevan Freeborn <65925598+StevanFreeborn@users.noreply.github.com> Date: Mon, 16 Dec 2024 14:28:09 -0600 Subject: [PATCH] feat: work on day 15 part 1 --- 10/HoofIt/Direction.cs | 10 +- 10/HoofIt/Position.cs | 4 +- 15/WarehouseWoes/Program.cs | 182 +++++++++++++++++++++++++++++++++++- 3 files changed, 186 insertions(+), 10 deletions(-) diff --git a/10/HoofIt/Direction.cs b/10/HoofIt/Direction.cs index 560b198..1ebc3fd 100644 --- a/10/HoofIt/Direction.cs +++ b/10/HoofIt/Direction.cs @@ -1,9 +1,9 @@ namespace HoofIt; -record Direction(int XD, int YD) +record Direction(int Xd, int Yd) { - public static Direction Up = new(0, -1); - public static Direction Down = new(0, 1); - public static Direction Left = new(-1, 0); - public static Direction Right = new(1, 0); + public static readonly Direction Up = new(0, -1); + public static readonly Direction Down = new(0, 1); + public static readonly Direction Left = new(-1, 0); + public static readonly Direction Right = new(1, 0); } \ No newline at end of file diff --git a/10/HoofIt/Position.cs b/10/HoofIt/Position.cs index ad8e337..e838f84 100644 --- a/10/HoofIt/Position.cs +++ b/10/HoofIt/Position.cs @@ -4,8 +4,8 @@ record Position(int X, int Y, int Height) { public bool TryGetNextPosition(Direction direction, string[] grid, out Position nextPosition) { - var x = X + direction.XD; - var y = Y + direction.YD; + var x = X + direction.Xd; + var y = Y + direction.Yd; nextPosition = new(x, y, -1); diff --git a/15/WarehouseWoes/Program.cs b/15/WarehouseWoes/Program.cs index 5f94bf8..810eed3 100644 --- a/15/WarehouseWoes/Program.cs +++ b/15/WarehouseWoes/Program.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Runtime.Intrinsics.X86; if (args.Length is 0) { @@ -13,12 +14,187 @@ if (File.Exists(args[0]) is false) } var isPart2 = args.Length is 2 && args[1] is "part2"; -var input = await File.ReadAllLinesAsync(args[0]); +var input = await File.ReadAllTextAsync(Path.Combine(AppContext.BaseDirectory, "INPUT.txt")); var stopwatch = new Stopwatch(); stopwatch.Start(); -// TODO: Implement solution +var inputParts = input.Split($"{Environment.NewLine}{Environment.NewLine}"); + +var mapLines = inputParts[0].Split(Environment.NewLine); + +var directions = inputParts[1] + .Where(character => character.ToString() != Environment.NewLine && character.ToString() != string.Empty) + .Select(Direction.From) + .ToList(); + +var result = WarehouseMap.From(mapLines) + .MoveRobot(directions) + .CalculateTotalBoxGpsCoordinates(); stopwatch.Stop(); -Console.WriteLine($". ({stopwatch.ElapsedMilliseconds}ms)"); \ No newline at end of file +Console.WriteLine($"The sum of all boxes' GPS coordinates is {result}. ({stopwatch.ElapsedMilliseconds}ms)"); + +class WarehouseMap +{ + private const char Robot = '@'; + private const char Wall = '#'; + private const char Box = 'O'; + private const char Empty = '.'; + + private readonly Dictionary _positions; + private Position RobotPosition => _positions.First(kvp => kvp.Value is Robot).Key; + + private WarehouseMap(Dictionary positions) + { + _positions = positions; + } + + public static WarehouseMap From(string[] input) + { + var positions = new Dictionary(); + + for (int y = 0; y < input.Length; y++) + { + for (int x = 0; x < input[0].Length; x++) + { + positions.Add(new(x, y), input[y][x]); + } + } + + return new(positions); + } + + public WarehouseMap MoveRobot(List directions) + { + var positions = _positions.ToDictionary(); + var robotPosition = RobotPosition; + + foreach (var direction in directions) + { + var nextPosition = robotPosition.GetNextPosition(direction); + var hasNextPosition = positions.TryGetValue(nextPosition, out var nextPositionValue); + + if (hasNextPosition is false) + { + continue; + } + + if (nextPositionValue is Wall) + { + continue; + } + + if (nextPositionValue is Empty) + { + positions[robotPosition] = Empty; + positions[nextPosition] = Robot; + continue; + } + + if (nextPositionValue is Box && CanPushBox(nextPosition, direction, positions)) + { + if (CanPushBox(nextPosition, direction, positions)) + { + positions = PushBox(nextPosition, direction, positions); + positions[robotPosition] = Empty; + positions[nextPosition] = Robot; + } + } + } + + return new(positions); + } + + public int CalculateTotalBoxGpsCoordinates() => _positions + .Where(kvp => kvp.Value is Box) + .Select(kvp => kvp.Key) + .Sum(p => p.GpsCoordinate); + + private static bool CanPushBox(Position boxPosition, Direction direction, Dictionary positions) + { + while (true) + { + var nextPosition = boxPosition.GetNextPosition(direction); + var hasNextPosition = positions.TryGetValue(nextPosition, out var nextPositionValue); + + if (hasNextPosition is false) + { + return false; + } + + switch (nextPositionValue) + { + case Box: + boxPosition = nextPosition; + continue; + case Empty: + return true; + default: + return false; + } + } + } + + private static Dictionary PushBox(Position boxPosition, Direction direction, Dictionary currentPositions) + { + while (true) + { + var positions = currentPositions.ToDictionary(); + var nextPosition = boxPosition.GetNextPosition(direction); + var hasNextPosition = positions.TryGetValue(nextPosition, out var nextPositionValue); + + if (hasNextPosition is false) + { + return positions; + } + + if (nextPositionValue is Box) + { + boxPosition = nextPosition; + currentPositions = positions; + continue; + } + + positions[boxPosition] = Empty; + positions[nextPosition] = Box; + + return positions; + } + } +} + +record Position(int X, int Y) +{ + public int GpsCoordinate => (100 * Y) + X; + + public Position GetNextPosition(Direction direction) + { + return new(X + direction.Xd, Y + direction.Yd); + } +} + +record Direction(int Xd, int Yd) +{ + private const char UpCharacter = '^'; + private const char RightCharacter = '>'; + private const char DownCharacter = 'v'; + private const char LeftCharacter = '<'; + + public static readonly Direction Up = new(0, -1); + public static readonly Direction Down = new(0, 1); + public static readonly Direction Left = new(-1, 0); + public static readonly Direction Right = new(1, 0); + + public static Direction From(char character) + { + return character switch + { + UpCharacter => Up, + RightCharacter => Right, + DownCharacter => Down, + LeftCharacter => Left, + _ => throw new ArgumentException(@$"{nameof(character)} is not a valid: {character}"), + }; + } +} \ No newline at end of file