diff --git a/Data/2024_08.txt b/Data/2024_08.txt
new file mode 100644
index 0000000..17d1fd1
--- /dev/null
+++ b/Data/2024_08.txt
@@ -0,0 +1,50 @@
+...........V..................b.g.................
+..................................g...............
+.............................c....................
+............T........Z.......P....................
+.x........................VP......................
+..........................PH......................
+.................H.....Z.......g.R................
+......f............T.V....b......A................
+......................P...........................
+.......f..................A.............R.........
+........x..............T.......l..H.....A.c.......
+..k..x..............Z.............................
+........5....S...............0.A..................
+.............N....L...............................
+.f............................T........s.....N....
+..................l..........bH.......tc.R..N.....
+......Z...6......n......l...k.N...0...............
+...........g....S......l.r.................t..s...
+..L................b.......K..t...................
+................5....n........0.............c.....
+.....L......n............................E........
+.k.......L................m.....................Es
+..............St.....5....Rm......................
+............6..5...................3...0..........
+...........k.................W........3...........
+................n......K...E....2S..........3.....
+....................................E....Q........
+..........M.....x...............K.................
+..h.............................1.................
+.6............z..............4...e.........WY....y
+........f............a.......Y..y...s.............
+...h............r.............v....m..............
+.....h.................v....m.....Y.Q.....W3......
+.........................Yq....Q.................7
+.........6..............7.................9.......
+...................X..........y..q.....2..........
+............r..............q.....y...........7.8..
+..B..............M....4............9..............
+...1.......M...X.......CGzp...4..B...2..K.........
+.....................z...v....Q.....8...........9.
+B.......X.F....rM...v...............2...8..D......
+h1..............................7..D.....8....d...
+...............F.....................9D....4....d.
+..........a......p............F.........W.D......d
+.........................G..C...........q.........
+...B..................................C...........
+.........w..........z....p.....................e..
+.a............G....w........p........F........e...
+........a...w.....................................
+........w...............XC.......G................
diff --git a/Solutions/2024/Day08.cs b/Solutions/2024/Day08.cs
new file mode 100644
index 0000000..a6f58a1
--- /dev/null
+++ b/Solutions/2024/Day08.cs
@@ -0,0 +1,67 @@
+using System.Reflection.Emit;
+
+namespace AdventOfCode.Solutions._2024;
+
+///
+/// Day 08: Resonant Collinearity
+/// https://adventofcode.com/2024/day/08
+///
+[Description("Resonant Collinearity")]
+public static partial class Day08 {
+
+ private static char[,] _map = default!;
+ private static ILookup _antennae = default!;
+
+ [Init]
+ public static void LoadMap(string[] input)
+ {
+ _map = input.To2dArray();
+ _antennae = _map
+ .ForEachCell()
+ .Where(c => char.IsAsciiLetterOrDigit(c))
+ .ToLookup(a => a.Value, a => a.Index);
+ }
+
+ public static int Part1(string[] _, Action? visualise = null)
+ {
+ List antinodes = [.._antennae
+ .Select(a => _antennae[a.Key])
+ .Select(locations => locations.Antinodes())
+ .SelectMany(antinodes => antinodes)
+ .Distinct()
+ .Where(antinode => _map.IsInBounds(antinode))];
+
+ _map.VisualiseMap(antinodes, "Final", visualise);
+ return antinodes.Count;
+ }
+
+ public static string Part2(string[] _) => NO_SOLUTION_WRITTEN_MESSAGE;
+
+ private static IEnumerable Antinodes(this IEnumerable locations)
+ {
+ foreach (IEnumerable item in locations.Combinations(2)) {
+ Point a1 = item.First();
+ Point a2 = item.Last();
+ yield return a1 - a2 + a1;
+ yield return a2 - a1 + a2;
+ }
+ }
+
+
+ public static void VisualiseMap(this char[, ] map, IEnumerable antinodes, string title, Action? visualise)
+ {
+ char[,] copy = (char[,])map.Clone();
+
+ foreach (Point antinode in antinodes) {
+ copy[antinode.X, antinode.Y] = ANTINODE;
+ }
+
+ if (visualise is not null) {
+ string[] output = ["", title, .. copy.PrintAsStringArray(0)];
+ _ = Task.Run(() => visualise?.Invoke(output, false));
+ }
+ }
+
+ private const char EMPTY = '.';
+ private const char ANTINODE = '#';
+}
diff --git a/Tests/2024/Tests_08.cs b/Tests/2024/Tests_08.cs
new file mode 100644
index 0000000..f02cea8
--- /dev/null
+++ b/Tests/2024/Tests_08.cs
@@ -0,0 +1,39 @@
+namespace AdventOfCode.Tests.Year2024;
+
+public class Tests_08_Resonant_Collinearity(ITestOutputHelper testOutputHelper)
+{
+ const int DAY = 08;
+
+ private const string TEST_DATA = """
+ ............
+ ........0...
+ .....0......
+ .......0....
+ ....0.......
+ ......A.....
+ ............
+ ............
+ ........A...
+ .........A..
+ ............
+ ............
+ """;
+
+ [Theory]
+ [InlineData(TEST_DATA, 14)]
+ public void Part1(string input, int expected)
+ {
+ _ = int.TryParse(SolutionRouter.SolveProblem(YEAR, DAY, PART1, input, new Action(Callback)), 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));
+ }
+}