Skip to content

Commit ab3d90f

Browse files
committed
Add day 15 puzzles solvers
Add day 15 puzzles solvers
1 parent 0fb9bdd commit ab3d90f

File tree

4 files changed

+123
-5
lines changed

4 files changed

+123
-5
lines changed

src/AdventOfCode2021.Runner/TodayPuzzleTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using AdventOfCode.Year2021.Solvers.Day14;
1+
using AdventOfCode.Year2021.Solvers;
22

33
using Xunit;
44
using Xunit.Abstractions;
@@ -18,13 +18,13 @@ public TodayPuzzleTests(ITestOutputHelper output)
1818
public async Task Result_should_be_accepted_by_site()
1919
{
2020
await Runner.
21-
Solve<IInputEntry, long>(2021, 14, 1).
22-
AssertingResult(Helpers.ParseLine).
21+
Solve<byte[], int>(2021, 15, 1).
22+
AssertingResult(Parsing.ParseToDigitsArray).
2323
Run(_output);
2424

2525
await Runner.
26-
Solve<IInputEntry, long>(2021, 14, 2).
27-
AssertingResult(Helpers.ParseLine).
26+
Solve<byte[], int>(2021, 15, 2).
27+
AssertingResult(Parsing.ParseToDigitsArray).
2828
Run(_output);
2929
}
3030
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace AdventOfCode.Year2021.Solvers.Day15;
2+
3+
public sealed class Day15Level1Solver : Day15SolverBase
4+
{
5+
protected override int DimensionsExtendMultiplier => 1;
6+
7+
protected override int Cost((int, int) location, byte[][] costs)
8+
{
9+
(int row, int col) = location;
10+
return costs[row][col];
11+
}
12+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace AdventOfCode.Year2021.Solvers.Day15;
2+
3+
public sealed class Day15Level2Solver : Day15SolverBase
4+
{
5+
protected override int DimensionsExtendMultiplier => 5;
6+
7+
protected override int Cost((int, int) location, byte[][] costs)
8+
{
9+
(int col, int row) = location;
10+
int height = costs.Length;
11+
int width = costs[0].Length;
12+
int baseCost = costs[row % height][col % width];
13+
int increment = row / height + col / width;
14+
int cost = baseCost + increment;
15+
return (cost - 1) % 9 + 1;
16+
}
17+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
namespace AdventOfCode.Year2021.Solvers.Day15;
2+
3+
public abstract class Day15SolverBase : SolverWithArrayInput<byte[], int>
4+
{
5+
protected override int Solve(byte[][] costs)
6+
{
7+
return new InnerSolver(costs, Cost, DimensionsExtendMultiplier).Solve();
8+
}
9+
10+
protected abstract int DimensionsExtendMultiplier { get; }
11+
protected abstract int Cost((int row, int col) location, byte[][] costs);
12+
13+
14+
private class InnerSolver
15+
{
16+
private readonly int _dimensionsExtendMultiplier;
17+
private readonly Func<(int row, int col), int> _getCost;
18+
private readonly int _height;
19+
private readonly int _width;
20+
21+
public InnerSolver(
22+
byte[][] costs,
23+
Func<(int row, int col), byte[][], int> getCost,
24+
int dimensionsExtendMultiplier
25+
)
26+
{
27+
_height = costs.Length;
28+
_width = costs[0].Length;
29+
_getCost = l => getCost(l, costs);
30+
_dimensionsExtendMultiplier = dimensionsExtendMultiplier;
31+
}
32+
33+
public int Solve()
34+
{
35+
var startLocation = (0, 0);
36+
var extension = new HashSet<(int row, int col)> { startLocation };
37+
var reached = new Dictionary<(int, int), int> { { startLocation, 0 } };
38+
39+
while (extension.Any())
40+
{
41+
extension = Extend(extension, reached);
42+
}
43+
44+
var endLocation = (_height * _dimensionsExtendMultiplier - 1, _width * _dimensionsExtendMultiplier - 1);
45+
return reached[endLocation];
46+
}
47+
48+
private HashSet<(int, int)> Extend(
49+
HashSet<(int, int)> prevExtension,
50+
Dictionary<(int, int), int> reached
51+
)
52+
{
53+
var extension = new HashSet<(int, int)>();
54+
foreach (var location in prevExtension)
55+
{
56+
int locationTotalCost = reached[location];
57+
ForAdjacent(location, a => processAdjacent(a, locationTotalCost));
58+
}
59+
return extension;
60+
61+
void processAdjacent((int row, int col) adjacent, int locationTotalCost)
62+
{
63+
int newAdjacentTotalCost = _getCost(adjacent) + locationTotalCost;
64+
if (reached.TryGetValue(adjacent, out int adjacentTotalCost))
65+
{
66+
if (newAdjacentTotalCost >= adjacentTotalCost) return;
67+
reached[adjacent] = newAdjacentTotalCost;
68+
}
69+
else
70+
{
71+
reached.Add(adjacent, newAdjacentTotalCost);
72+
}
73+
extension.Add(adjacent);
74+
}
75+
}
76+
77+
private void ForAdjacent((int, int) location, Action<(int, int)> action)
78+
{
79+
int height = _height * _dimensionsExtendMultiplier;
80+
int width = _width * _dimensionsExtendMultiplier;
81+
82+
(int row, int col) = location;
83+
if (row > 0) action((row - 1, col));
84+
if (row < height - 1) action((row + 1, col));
85+
if (col > 0) action((row, col - 1));
86+
if (col < width - 1) action((row, col + 1));
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)