Skip to content

Commit f851888

Browse files
committed
2024 Day 16 Part 1
1 parent 9496beb commit f851888

File tree

3 files changed

+117
-2
lines changed

3 files changed

+117
-2
lines changed

src/2024/16/Program.cs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,93 @@
11
using AdventOfCode.Common;
2+
using Coor = AdventOfCode.Common.Coor<int>;
23

3-
var lines = Resources.GetInputFileLines();
4+
var map = Resources.GetInputFileLines()
5+
.ParseAsArray();
46

5-
Console.WriteLine($"Part 1: {""}");
7+
var start = map.AllCoordinates().First(c => map.Get(c) == 'S');
8+
var corner = new[]
9+
{
10+
(Coor.Up, Coor.Left),
11+
(Coor.Up, Coor.Right),
12+
(Coor.Down, Coor.Left),
13+
(Coor.Down, Coor.Right),
14+
};
15+
var end = map.AllCoordinates().First(c => map.Get(c) == 'E');
16+
var direction = Coor.Right;
17+
18+
// Places where we can change direction
19+
var crossroads = map.AllCoordinates()
20+
.Where(c => map.Get(c) == '.' && corner.Any(d => map.Get(c + d.Item1) == '.' && map.Get(c + d.Item2) == '.'))
21+
.Append(start)
22+
.Append(end)
23+
.ToHashSet();
24+
25+
var neighbours = new Dictionary<Coor, List<(Coor Neighbour, int Distance)>>();
26+
27+
foreach (var c in crossroads)
28+
{
29+
foreach (var dir in Coor.FourWayNeighbours)
30+
{
31+
var current = c;
32+
var dist = 0;
33+
do
34+
{
35+
current += dir;
36+
dist++;
37+
38+
if (crossroads.Contains(current))
39+
{
40+
if (!neighbours.TryGetValue(c, out var list))
41+
{
42+
list = [];
43+
neighbours[c] = list;
44+
}
45+
list.Add((current, dist));
46+
break;
47+
}
48+
} while (map.Get(current) == '.');
49+
}
50+
}
51+
52+
var scores = Resources.GetInputFileLines()
53+
.ParseAsArray(c => c switch
54+
{
55+
'S' => 0,
56+
'#' => int.MinValue,
57+
_ => int.MaxValue,
58+
});
59+
60+
var shortestPaths = new Dictionary<Coor, List<Coor>>();
61+
var queue = new PriorityQueue<State, int>();
62+
queue.Enqueue(new(start, Coor.Right, []), 0);
63+
64+
while (queue.TryDequeue(out var current, out var score))
65+
{
66+
if (scores.Get(current.Position) < score) continue;
67+
68+
scores.Set(current.Position, score);
69+
shortestPaths[current.Position] = current.Path;
70+
71+
if (!neighbours.TryGetValue(current.Position, out var currentNeighbours))
72+
{
73+
continue;
74+
}
75+
76+
foreach (var nc in currentNeighbours.Where(n => n.Neighbour != current.Position))
77+
{
78+
var newDirection = (current.Position - nc.Neighbour).Normalize();
79+
var newScore = score + nc.Distance + (newDirection == current.Direction ? 0 : 1000);
80+
if (scores.Get(nc.Neighbour) > newScore)
81+
{
82+
queue.Enqueue(new(nc.Neighbour, newDirection, [..current.Path, nc.Neighbour]), newScore);
83+
}
84+
}
85+
}
86+
87+
var shortestPath = shortestPaths[end];
88+
map.Print(c => shortestPath.Contains(c) ? ('*', ConsoleColor.Cyan) : (map.Get(c), ConsoleColor.White));
89+
90+
Console.WriteLine($"Part 1: {scores.Get(end)}");
691
Console.WriteLine($"Part 2: {""}");
92+
93+
file record struct State(Coor Position, Coor Direction, List<Coor> Path);

src/Common/Coor.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ public IEnumerable<Coor<T>> GetFourWayNeighbours()
6060
{ 'v', Down },
6161
};
6262

63+
public Coor<T> Normalize()
64+
{
65+
T x = T.Zero;
66+
if (X > T.Zero) x = T.One;
67+
if (X < T.Zero) x = -T.One;
68+
T y = T.Zero;
69+
if (Y > T.Zero) y = T.One;
70+
if (Y < T.Zero) y = -T.One;
71+
return new Coor<T>(y, x);
72+
}
73+
6374
public static bool operator ==(Coor<T> me, (T, T) other) => new Coor<T>(other.Item1, other.Item2) == me;
6475
public static bool operator !=(Coor<T> me, (T, T) other) => !(me == other);
6576
public static Coor<T> operator +(Coor<T> me, (T, T) other) => new(Y: me.Y + other.Item1, X: me.X + other.Item2);

src/Common/MultiDimensionalArrayExtensions.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,23 @@ public static void Print<T>(this T[,] map, Func<Coor<int>, char> printOverride)
8888
}
8989
}
9090

91+
public static void Print<T>(this T[,] map, Func<Coor<int>, (char, ConsoleColor)> printOverride)
92+
{
93+
for (var y = 0; y < map.Height(); y++)
94+
{
95+
for (var x = 0; x < map.Width(); x++)
96+
{
97+
var tmp = Console.ForegroundColor;
98+
var c = printOverride.Invoke(new(y, x));
99+
Console.ForegroundColor = c.Item2;
100+
Console.Write(c.Item1);
101+
Console.ForegroundColor = tmp;
102+
}
103+
104+
Console.WriteLine();
105+
}
106+
}
107+
91108
// Returns a set of vectors of possible ways to traverse a rectangle:
92109
// - Rows
93110
// - Columns

0 commit comments

Comments
 (0)