Took me a little while to understand the problem, but once I did, ivec2 came in clutch once again.

Would have had part 2 sooner if not for the "also all antennas are now antinodes" thing which I just missed. You win again, reading comprehension.
This commit is contained in:
2024-12-08 12:47:53 -06:00
parent 57ed9d261e
commit 61ba061c6b
3 changed files with 105 additions and 15 deletions

93
src/08.cs Normal file
View File

@ -0,0 +1,93 @@
using aoc2024.Util;
namespace aoc2024;
internal class Day08 : Day
{
private readonly Dictionary<char, List<ivec2>> antennas = [];
private ivec2 dimensions = ivec2.ZERO;
internal override void Parse()
{
var lines = Util.Parsing.ReadAllLines($"{GetDay()}").ToList();
dimensions = new ivec2(lines[0].Length, lines.Count);
for (int i = 0; i < lines.Count; i++)
{
var line = lines[i];
for (int j = 0; j < line.Length; j++)
{
if (line[j] == '.' || line[j] == '#')
{
continue;
}
var loc = new ivec2(j, i);
if (!antennas.TryAdd(line[j], [loc]))
{
antennas[line[j]].Add(loc);
}
}
}
}
internal override string Part1()
{
HashSet<ivec2> antinodes = [];
foreach (var (_, locs) in antennas)
{
foreach (var loc in locs)
{
var others = locs.Except([loc]);
foreach (var other in others)
{
var between = loc - other;
var a1 = loc + between;
var a2 = other - between;
if (a1.IsWithinRange(0, 0, dimensions.x - 1, dimensions.y - 1))
{
antinodes.Add(loc + between);
}
if (a2.IsWithinRange(0, 0, dimensions.x - 1, dimensions.y - 1))
{
antinodes.Add(other - between);
}
}
}
}
return $"# antinodes: <+white>{antinodes.Count}";
}
internal override string Part2()
{
HashSet<ivec2> antinodes = [];
foreach (var (_, locs) in antennas)
{
antinodes.UnionWith(locs);
foreach (var loc in locs)
{
var others = locs.Except([loc]);
foreach (var other in others)
{
var between = loc - other;
var a1 = loc + between;
var a2 = other - between;
while (a1.IsWithinRange(0, 0, dimensions.x - 1, dimensions.y - 1))
{
antinodes.Add(a1);
a1 += between;
}
while (a2.IsWithinRange(0, 0, dimensions.x - 1, dimensions.y - 1))
{
antinodes.Add(a2);
a2 -= between;
}
}
}
}
return $"# antinodes including harmonics: <+white>{antinodes.Count}";
}
}

View File

@ -74,7 +74,7 @@ public readonly struct ivec2 : IEquatable<ivec2>, IComparable<ivec2>, IComparabl
}
}
public IEnumerable<ivec2> GetBoundedOrthogonalNeighbors(int minX, int minY, int maxX, int maxY)
public IEnumerable<ivec2> GetBoundedOrthogonalNeighbors(long minX, long minY, long maxX, long maxY)
{
foreach (var dir in FOURWAY)
{
@ -96,7 +96,7 @@ public readonly struct ivec2 : IEquatable<ivec2>, IComparable<ivec2>, IComparabl
}
}
public IEnumerable<ivec2> GetBoundedNeighbors(int minX, int minY, int maxX, int maxY)
public IEnumerable<ivec2> GetBoundedNeighbors(long minX, long minY, long maxX, long maxY)
{
foreach (var dir in EIGHTWAY)
{
@ -118,7 +118,7 @@ public readonly struct ivec2 : IEquatable<ivec2>, IComparable<ivec2>, IComparabl
}
}
public IEnumerable<ivec2> GetBoundedDiagonalNeighbors(int minX, int minY, int maxX, int maxY)
public IEnumerable<ivec2> GetBoundedDiagonalNeighbors(long minX, long minY, long maxX, long maxY)
{
foreach (var dir in DIAGONALS)
{
@ -149,17 +149,11 @@ public readonly struct ivec2 : IEquatable<ivec2>, IComparable<ivec2>, IComparabl
public static bool operator >(ivec2 a, ivec2 b) => (a.x > b.x) && (a.y > b.y);
public static bool operator >=(ivec2 a, ivec2 b) => (a.x >= b.x) && (a.y >= b.y);
public bool IsWithinRange(int minX, int minY, int maxX, int maxY) => x >= minX && y >= minY && x <= maxX && y <= maxY;
public bool IsWithinRange(long minX, long minY, long maxX, long maxY) => x >= minX && y >= minY && x <= maxX && y <= maxY;
public bool Equals(ivec2 other)
{
return x == other.x && y == other.y;
}
public bool Equals(ivec2 other) => x == other.x && y == other.y;
public override bool Equals(object? obj)
{
return obj is ivec2 other && Equals(other);
}
public override bool Equals(object? obj) => obj is ivec2 other && Equals(other);
public int CompareTo(ivec2 other)
{
@ -178,7 +172,11 @@ public readonly struct ivec2 : IEquatable<ivec2>, IComparable<ivec2>, IComparabl
public int CompareTo(object? obj)
{
if (ReferenceEquals(null, obj)) return 1;
if (obj is null)
{
return 1;
}
return obj is ivec2 other ? CompareTo(other) : throw new ArgumentException($"Object must be of type {nameof(ivec2)}");
}

View File

@ -115,12 +115,11 @@ else
foreach (var desiredDay in desiredDays)
{
Day? day = getDayInstanceFromArg(desiredDay);
using Day? day = getDayInstanceFromArg(desiredDay);
if (day == null)
{
Logger.LogLine($"Unknown day <cyan>{desiredDay}<r>");
}
day?.Go(runPart1 ?? true, runPart2 ?? true);
day?.Dispose();
}