Skip to content

Commit

Permalink
2024 Day18 Part1 Solved
Browse files Browse the repository at this point in the history
smabuk committed Dec 18, 2024
1 parent 6738175 commit 7855402
Showing 3 changed files with 3,620 additions and 0 deletions.
3,450 changes: 3,450 additions & 0 deletions Data/2024_18.txt

Large diffs are not rendered by default.

119 changes: 119 additions & 0 deletions Solutions/2024/Day18.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
namespace AdventOfCode.Solutions._2024;

/// <summary>
/// Day 18: RAM Run
/// https://adventofcode.com/2024/day/18
/// </summary>
[Description("RAM Run")]
public static partial class Day18 {

private static List<Point> _bytes = default!;
private static Action<string[], bool>? _visualise = null;

[Init]
public static void Init(string[] input, Action<string[], bool>? visualise = null)
{
_bytes = [.. input.Select(i => i.As<Point>())];
_visualise = visualise;
}

public static int Part1(string[] _, params object[]? args)
{
int gridSize = args.GridSize();
int noOfBytes = args.Bytes();

Point start = Point.Zero;
Point end = new(gridSize - 1, gridSize - 1);

_bytes.Take(noOfBytes).VisualiseRam("Initial state:", gridSize, []);

List<Point> shortestPath = FindShortestPath(start, end, _bytes.Take(noOfBytes), gridSize);

_bytes.Take(noOfBytes).VisualiseRam("Final:", gridSize, shortestPath);

return shortestPath.Count - 1; // shortestPath includes start
}

public static List<Point> FindShortestPath(Point start, Point goal, IEnumerable<Point> obstacles, int gridSize)
{
PriorityQueue<Point, int> priorityQueue = new();
Dictionary<Point, int> cost = new() { [start] = 0 };
Dictionary<Point, int> distances = new() { [start] = start.ManhattanDistance(goal) };
Dictionary<Point, Point> previous = [];

HashSet<Point> obstaclesSet = [.. obstacles];

priorityQueue.Enqueue(start, distances[start]);

while (priorityQueue.Count > 0) {
Point current = priorityQueue.Dequeue();

if (current == goal) {
return ReconstructPath(previous, current);
}

foreach (Direction direction in Directions.NSEW) {
Point adjacent = current + direction.Delta();

// Ignore invalid neighbours
if (adjacent.X < 0 || adjacent.Y < 0 || adjacent.X >= gridSize || adjacent.Y >= gridSize
|| obstaclesSet.Contains(adjacent)) {
continue;
}

int tentativeCost = cost[current] + 1;

if (tentativeCost < cost.GetValueOrDefault(adjacent, int.MaxValue)) {
previous[adjacent] = current;
cost[adjacent] = tentativeCost;
distances[adjacent] = tentativeCost + adjacent.ManhattanDistance(goal);

// Add to priority queue with updated distance score
priorityQueue.Enqueue(adjacent, distances[adjacent]);
}
}
}

return []; // No path found
}

private static List<Point> ReconstructPath(Dictionary<Point, Point> cameFrom, Point current)
{
List<Point> totalPath = [current];

while (cameFrom.ContainsKey(current)) {
current = cameFrom[current];
totalPath.Insert(0, current);
}

return totalPath;
}


public static string Part2(string[] input, params object[]? args) => NO_SOLUTION_WRITTEN_MESSAGE;

private static void VisualiseRam(this IEnumerable<Point> bytes, string title, int gridSize, IEnumerable<Point> route, bool clearScreen = false)
{
if (_visualise is null) {
return;
}

char[,] outputRamMap = new char[gridSize, gridSize];
outputRamMap.FillInPlace('.');

foreach (Point position in bytes ?? []) {
outputRamMap[position.X, position.Y] = '#';
}

foreach (Point position in route ?? []) {
outputRamMap[position.X, position.Y] = 'O';
}

string[] output = ["", title, .. outputRamMap.AsStrings()/*.Select(s => s.Replace('.', ' '))*/];
_visualise?.Invoke(output, clearScreen);
}

private static int GridSize(this object[]? args) => GetArgument(args, 1, 71);
private static int Bytes(this object[]? args) => GetArgument(args, 2, 1024);

}
51 changes: 51 additions & 0 deletions Tests/2024/Tests_18.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
namespace AdventOfCode.Tests.Year2024;

public class Tests_18_RAM_Run(ITestOutputHelper testOutputHelper)
{
const int DAY = 18;

[Theory]
[InlineData("""
5,4
4,2
4,5
3,0
2,1
6,3
2,4
1,5
0,6
3,3
2,6
5,1
1,2
5,5
2,5
6,5
1,4
0,4
6,4
1,1
6,1
1,0
0,5
1,6
2,0
""", 7, 12, 22)]
public void Part1(string input, int gridSize, int bytes, int expected)
{
_ = int.TryParse(SolutionRouter.SolveProblem(YEAR, DAY, PART1, input, new Action<string[], bool>(Callback), gridSize, bytes), out int actual);
actual.ShouldBe(expected);
}


private void Callback(string[] lines, bool _)
{
if (lines is null or []) {
return;
}

testOutputHelper.WriteLine(string.Join(Environment.NewLine, lines));
}

}

0 comments on commit 7855402

Please sign in to comment.