feat: solved day 15 part 1...this was were i made it too last year
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
namespace WarehouseWoes.Tests;
|
||||||
|
|
||||||
|
public class PuzzleParserTests
|
||||||
|
{
|
||||||
|
private async Task<string> GetPuzzleInput()
|
||||||
|
{
|
||||||
|
return await File.ReadAllTextAsync(Path.Combine(AppContext.BaseDirectory, "INPUT.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Parse_WhenCalled_ItShouldReturnMapAndDirections()
|
||||||
|
{
|
||||||
|
var input = await GetPuzzleInput();
|
||||||
|
var result = PuzzleParser.Parse(input);
|
||||||
|
|
||||||
|
await Assert.That(result.Map).IsTypeOf<WarehouseMap>();
|
||||||
|
await Assert.That(result.Directions).IsTypeOf<List<Direction>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task PartOneSolution_WhenGivenPuzzleInput_ItShouldReturnExpectedSolution()
|
||||||
|
{
|
||||||
|
var input = await GetPuzzleInput();
|
||||||
|
var (map, directions) = PuzzleParser.Parse(input);
|
||||||
|
|
||||||
|
var result = map.MoveRobot(directions).CalculateTotalBoxGpsCoordinates();
|
||||||
|
|
||||||
|
await Assert.That(result).IsEqualTo(1318523);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,443 @@
|
|||||||
|
namespace WarehouseWoes.Tests;
|
||||||
|
|
||||||
|
public class WarehouseMapTests
|
||||||
|
{
|
||||||
|
private static readonly string[] LargeExampleMap = [
|
||||||
|
"##########",
|
||||||
|
"#..O..O.O#",
|
||||||
|
"#......O.#",
|
||||||
|
"#.OO..O.O#",
|
||||||
|
"#..O@..O.#",
|
||||||
|
"#O#..O...#",
|
||||||
|
"#O..O..O.#",
|
||||||
|
"#.OO.O.OO#",
|
||||||
|
"#....O...#",
|
||||||
|
"##########",
|
||||||
|
];
|
||||||
|
|
||||||
|
private static readonly string[] SmallExampleMap = [
|
||||||
|
"########",
|
||||||
|
"#..O.O.#",
|
||||||
|
"##@.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
];
|
||||||
|
|
||||||
|
private static readonly string[] LargeExampleDirections = [
|
||||||
|
"<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^",
|
||||||
|
"vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v",
|
||||||
|
"><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<",
|
||||||
|
"<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^",
|
||||||
|
"^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><",
|
||||||
|
"^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^",
|
||||||
|
">^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^",
|
||||||
|
"<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>",
|
||||||
|
"^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>",
|
||||||
|
"v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^",
|
||||||
|
];
|
||||||
|
|
||||||
|
private static readonly string[] SmallExampleDirections = [
|
||||||
|
"<^^>>>vv<v>>v<<",
|
||||||
|
];
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[MethodDataSource(nameof(MoveTestCases))]
|
||||||
|
public async Task Move_WhenCalled_ItShouldMoveValuesToExpectedPositions(MoveTestCase testCase)
|
||||||
|
{
|
||||||
|
var expected = WarehouseMap.From(testCase.ExpectedMap);
|
||||||
|
var directions = testCase.Directions.Select(Direction.From).ToList();
|
||||||
|
|
||||||
|
var result = WarehouseMap.From(testCase.MapInput).MoveRobot(directions);
|
||||||
|
|
||||||
|
await Assert.That(result.Positions).IsEquivalentTo(expected.Positions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Func<MoveTestCase>> MoveTestCases()
|
||||||
|
{
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#..O.O.#",
|
||||||
|
"##@.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"<",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#..O.O.#",
|
||||||
|
"##@.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#..O.O.#",
|
||||||
|
"##@.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"^",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#.@O.O.#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#.@O.O.#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"^",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#.@O.O.#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#.@O.O.#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
">",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#..@OO.#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#..@OO.#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
">",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#...@OO#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#...@OO#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
">",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#...@OO#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#...@OO#",
|
||||||
|
"##..O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#......#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"v",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##..@..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##..@..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"v",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##..@..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##..@..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"<",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.@...#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.@...#",
|
||||||
|
"#...O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"v",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#..@O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#..@O..#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
">",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#...@O.#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#...@O.#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
">",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#....@O#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#....@O#",
|
||||||
|
"#.#.O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"v",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#.....O#",
|
||||||
|
"#.#.O@.#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#.....O#",
|
||||||
|
"#.#.O@.#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"<",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#.....O#",
|
||||||
|
"#.#O@..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
yield return () => new(
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#.....O#",
|
||||||
|
"#.#O@..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
],
|
||||||
|
"<",
|
||||||
|
[
|
||||||
|
"########",
|
||||||
|
"#....OO#",
|
||||||
|
"##.....#",
|
||||||
|
"#.....O#",
|
||||||
|
"#.#O@..#",
|
||||||
|
"#...O..#",
|
||||||
|
"#...O..#",
|
||||||
|
"########",
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record MoveTestCase(string[] MapInput, string Directions, string[] ExpectedMap);
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[MethodDataSource(nameof(CalculateTotalBoxGpsCoordinatesTestCases))]
|
||||||
|
public async Task CalculateTotalBoxGpsCoordinates_WhenCalledWithExampleInput_ItShouldReturnExpectedValue(CalculateTotalBoxGpsCoordinatesTestCase testCase)
|
||||||
|
{
|
||||||
|
var map = WarehouseMap.From(testCase.MapInput);
|
||||||
|
var directions = string.Join(string.Empty, testCase.DirectionsInput).Select(Direction.From).ToList();
|
||||||
|
|
||||||
|
var mapAfterRobotMoved = map.MoveRobot(directions);
|
||||||
|
var result = mapAfterRobotMoved.CalculateTotalBoxGpsCoordinates();
|
||||||
|
|
||||||
|
await Assert.That(result).IsEqualTo(testCase.ExpectedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Func<CalculateTotalBoxGpsCoordinatesTestCase>> CalculateTotalBoxGpsCoordinatesTestCases()
|
||||||
|
{
|
||||||
|
yield return () => new(LargeExampleMap, LargeExampleDirections, 10092);
|
||||||
|
yield return () => new(SmallExampleMap, SmallExampleDirections, 2028);
|
||||||
|
}
|
||||||
|
|
||||||
|
public record CalculateTotalBoxGpsCoordinatesTestCase(string[] MapInput, string[] DirectionsInput, int ExpectedValue);
|
||||||
|
}
|
||||||
+66
-40
@@ -1,5 +1,5 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Text;
|
||||||
|
|
||||||
if (args.Length is 0)
|
if (args.Length is 0)
|
||||||
{
|
{
|
||||||
@@ -14,27 +14,38 @@ if (File.Exists(args[0]) is false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isPart2 = args.Length is 2 && args[1] is "part2";
|
var isPart2 = args.Length is 2 && args[1] is "part2";
|
||||||
var input = await File.ReadAllTextAsync(Path.Combine(AppContext.BaseDirectory, "INPUT.txt"));
|
var input = await File.ReadAllTextAsync(args[0]);
|
||||||
|
|
||||||
var stopwatch = new Stopwatch();
|
var stopwatch = new Stopwatch();
|
||||||
stopwatch.Start();
|
stopwatch.Start();
|
||||||
|
|
||||||
var inputParts = input.Split($"{Environment.NewLine}{Environment.NewLine}");
|
var (map, directions) = PuzzleParser.Parse(input);
|
||||||
|
var result = map.MoveRobot(directions).CalculateTotalBoxGpsCoordinates();
|
||||||
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();
|
stopwatch.Stop();
|
||||||
Console.WriteLine($"The sum of all boxes' GPS coordinates is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
|
Console.WriteLine($"The sum of all boxes' GPS coordinates is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
|
||||||
|
|
||||||
|
static class PuzzleParser
|
||||||
|
{
|
||||||
|
public static (WarehouseMap Map, List<Direction> Directions) Parse(string input)
|
||||||
|
{
|
||||||
|
var inputParts = input.Split($"{Environment.NewLine}{Environment.NewLine}");
|
||||||
|
|
||||||
|
var map = WarehouseMap.From(inputParts[0].Split(Environment.NewLine));
|
||||||
|
|
||||||
|
var directions = inputParts[1]
|
||||||
|
.Where(character =>
|
||||||
|
{
|
||||||
|
var str = character.ToString();
|
||||||
|
return str != "\r" && str != "\n" && str != "\r\n";
|
||||||
|
})
|
||||||
|
.Select(Direction.From)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return (map, directions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class WarehouseMap
|
class WarehouseMap
|
||||||
{
|
{
|
||||||
private const char Robot = '@';
|
private const char Robot = '@';
|
||||||
@@ -42,21 +53,20 @@ class WarehouseMap
|
|||||||
private const char Box = 'O';
|
private const char Box = 'O';
|
||||||
private const char Empty = '.';
|
private const char Empty = '.';
|
||||||
|
|
||||||
private readonly Dictionary<Position, char> _positions;
|
public readonly Dictionary<Position, char> Positions;
|
||||||
private Position RobotPosition => _positions.First(kvp => kvp.Value is Robot).Key;
|
|
||||||
|
|
||||||
private WarehouseMap(Dictionary<Position, char> positions)
|
private WarehouseMap(Dictionary<Position, char> positions)
|
||||||
{
|
{
|
||||||
_positions = positions;
|
Positions = positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WarehouseMap From(string[] input)
|
public static WarehouseMap From(string[] input)
|
||||||
{
|
{
|
||||||
var positions = new Dictionary<Position, char>();
|
var positions = new Dictionary<Position, char>();
|
||||||
|
|
||||||
for (int y = 0; y < input.Length; y++)
|
for (var y = 0; y < input.Length; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < input[0].Length; x++)
|
for (var x = 0; x < input[0].Length; x++)
|
||||||
{
|
{
|
||||||
positions.Add(new(x, y), input[y][x]);
|
positions.Add(new(x, y), input[y][x]);
|
||||||
}
|
}
|
||||||
@@ -67,11 +77,11 @@ class WarehouseMap
|
|||||||
|
|
||||||
public WarehouseMap MoveRobot(List<Direction> directions)
|
public WarehouseMap MoveRobot(List<Direction> directions)
|
||||||
{
|
{
|
||||||
var positions = _positions.ToDictionary();
|
var positions = Positions.ToDictionary();
|
||||||
var robotPosition = RobotPosition;
|
|
||||||
|
|
||||||
foreach (var direction in directions)
|
foreach (var direction in directions)
|
||||||
{
|
{
|
||||||
|
var robotPosition = positions.First(kvp => kvp.Value is Robot).Key;
|
||||||
var nextPosition = robotPosition.GetNextPosition(direction);
|
var nextPosition = robotPosition.GetNextPosition(direction);
|
||||||
var hasNextPosition = positions.TryGetValue(nextPosition, out var nextPositionValue);
|
var hasNextPosition = positions.TryGetValue(nextPosition, out var nextPositionValue);
|
||||||
|
|
||||||
@@ -80,36 +90,53 @@ class WarehouseMap
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextPositionValue is Wall)
|
switch (nextPositionValue)
|
||||||
{
|
{
|
||||||
|
case Wall:
|
||||||
continue;
|
continue;
|
||||||
}
|
case Empty:
|
||||||
|
|
||||||
if (nextPositionValue is Empty)
|
|
||||||
{
|
|
||||||
positions[robotPosition] = Empty;
|
positions[robotPosition] = Empty;
|
||||||
positions[nextPosition] = Robot;
|
positions[nextPosition] = Robot;
|
||||||
continue;
|
continue;
|
||||||
}
|
case Box when CanPushBox(nextPosition, direction, positions):
|
||||||
|
|
||||||
if (nextPositionValue is Box && CanPushBox(nextPosition, direction, positions))
|
|
||||||
{
|
|
||||||
if (CanPushBox(nextPosition, direction, positions))
|
|
||||||
{
|
|
||||||
positions = PushBox(nextPosition, direction, positions);
|
positions = PushBox(nextPosition, direction, positions);
|
||||||
positions[robotPosition] = Empty;
|
positions[robotPosition] = Empty;
|
||||||
positions[nextPosition] = Robot;
|
positions[nextPosition] = Robot;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new(positions);
|
return new(positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int CalculateTotalBoxGpsCoordinates() => _positions
|
public int CalculateTotalBoxGpsCoordinates()
|
||||||
.Where(kvp => kvp.Value is Box)
|
{
|
||||||
.Select(kvp => kvp.Key)
|
var boxes = Positions.Where(kvp => kvp.Value is Box).ToList();
|
||||||
.Sum(p => p.GpsCoordinate);
|
return boxes.Select(kvp => kvp.Key).Sum(p => p.GpsCoordinate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var maxX = Positions.Select(kvp => kvp.Key).Max(p => p.X);
|
||||||
|
var maxY = Positions.Select(kvp => kvp.Key).Max(p => p.Y);
|
||||||
|
|
||||||
|
var map = new StringBuilder();
|
||||||
|
|
||||||
|
for (var y = 0; y <= maxY; y++)
|
||||||
|
{
|
||||||
|
var row = new StringBuilder();
|
||||||
|
|
||||||
|
for (var x = 0; x <= maxX; x++)
|
||||||
|
{
|
||||||
|
var value = Positions[new(x, y)];
|
||||||
|
row.Append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.AppendLine(row.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return map.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
private static bool CanPushBox(Position boxPosition, Direction direction, Dictionary<Position, char> positions)
|
private static bool CanPushBox(Position boxPosition, Direction direction, Dictionary<Position, char> positions)
|
||||||
{
|
{
|
||||||
@@ -138,9 +165,10 @@ class WarehouseMap
|
|||||||
|
|
||||||
private static Dictionary<Position, Char> PushBox(Position boxPosition, Direction direction, Dictionary<Position, char> currentPositions)
|
private static Dictionary<Position, Char> PushBox(Position boxPosition, Direction direction, Dictionary<Position, char> currentPositions)
|
||||||
{
|
{
|
||||||
|
var positions = currentPositions.ToDictionary();
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var positions = currentPositions.ToDictionary();
|
|
||||||
var nextPosition = boxPosition.GetNextPosition(direction);
|
var nextPosition = boxPosition.GetNextPosition(direction);
|
||||||
var hasNextPosition = positions.TryGetValue(nextPosition, out var nextPositionValue);
|
var hasNextPosition = positions.TryGetValue(nextPosition, out var nextPositionValue);
|
||||||
|
|
||||||
@@ -152,11 +180,9 @@ class WarehouseMap
|
|||||||
if (nextPositionValue is Box)
|
if (nextPositionValue is Box)
|
||||||
{
|
{
|
||||||
boxPosition = nextPosition;
|
boxPosition = nextPosition;
|
||||||
currentPositions = positions;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
positions[boxPosition] = Empty;
|
|
||||||
positions[nextPosition] = Box;
|
positions[nextPosition] = Box;
|
||||||
|
|
||||||
return positions;
|
return positions;
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ EndProject
|
|||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WarehouseWoes.Tests", "15\WarehouseWoes.Tests\WarehouseWoes.Tests.csproj", "{055CE647-AEFA-4501-B518-D16FF400E3D0}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WarehouseWoes.Tests", "15\WarehouseWoes.Tests\WarehouseWoes.Tests.csproj", "{055CE647-AEFA-4501-B518-D16FF400E3D0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "16", "16", "{C50481FF-1766-4C51-BEE3-91BEC5642818}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "16", "16", "{C50481FF-1766-4C51-BEE3-91BEC5642818}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
16\INPUT.txt = 16\INPUT.txt
|
||||||
|
16\PROBLEM.md = 16\PROBLEM.md
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReindeerMaze", "16\ReindeerMaze\ReindeerMaze.csproj", "{5610FB67-037B-4C87-8D5D-E86D9D7DDB51}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReindeerMaze", "16\ReindeerMaze\ReindeerMaze.csproj", "{5610FB67-037B-4C87-8D5D-E86D9D7DDB51}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
Reference in New Issue
Block a user