advent24/Advent24/Day8.cs

105 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace Advent24
{
internal class Day8
{
public Day8()
{
String fileData = System.IO.File.ReadAllText(@"..\..\..\inputd8.txt");
// set this to false for part 1
Boolean enableResonantHarmonics = true;
// get width of line to be able to navigate the map block in
// both dimensions
Int32 mapWidth = fileData.IndexOf('\n');
Int32 mapWidthIncludingNewline = mapWidth + 1;
String pattern = @"[A-Za-z0-9]";
Regex r = new(pattern, RegexOptions.Multiline, TimeSpan.FromMilliseconds(150));
Match m = r.Match(fileData);
// list of linear-integer locations of antennas indexed by antenna type (a single alphanumeric character)
Dictionary<Char, List<Int32>> antennaLocationsMap = [];
while (m.Success)
{
if (!antennaLocationsMap.TryGetValue(m.Groups[0].Value[0], out List<int>? antennaLocations))
antennaLocationsMap.Add(m.Groups[0].Value[0], [m.Groups[0].Index]);
else
antennaLocationsMap[m.Groups[0].Value[0]].Add(m.Groups[0].Index);
// Console.WriteLine("antennaLocationsMap[{0:d}] = {1:d}", m.Groups[0].Value[0], antennaLocationsMap[m.Groups[0].Value[0]].Last());
m = m.NextMatch();
}
// set of linear-integer locations of antinodes indexed by antenna type (single-character alphanumeric)
Dictionary<Char, HashSet<Int32>> antinodeLocationsMap = [];
// set of linear-integer locations of antinodes overall
HashSet<Int32> overallAntinodeLocations = [];
foreach (Char antennaType in antennaLocationsMap.Keys)
{
if (!antinodeLocationsMap.TryGetValue(antennaType, out HashSet<int>? antinodeLocations))
antinodeLocationsMap.Add(antennaType, []);
// for each (ordered) pair of antennaLocations of the same antenna type, we'll construct an antinode
// and then add it to the antinodeLocationsMap (keyed by antenna type)
foreach(Int32 antennaLocation1 in antennaLocationsMap[antennaType])
foreach(Int32 antennaLocation2 in antennaLocationsMap[antennaType])
{
if (antennaLocation1 == antennaLocation2)
continue;
Int32 antennaLocationDifference = antennaLocation2 - antennaLocation1;
Int32 antennaLocationXDifference = (antennaLocation2 % mapWidthIncludingNewline) - (antennaLocation1 % mapWidthIncludingNewline);
Int32 antinodeLocation = antennaLocation2;
do
{
Int32 antinodePreviousLocationX = antinodeLocation % mapWidthIncludingNewline;
antinodeLocation += antennaLocationDifference;
Int32 antinodeLocationXDifference = (antinodeLocation % mapWidthIncludingNewline) - antinodePreviousLocationX;
// bounds checking
if (
antinodeLocation < 0 ||
antinodeLocation >= fileData.Length ||
fileData[antinodeLocation] == '\n' ||
// x-direction having changed implies we crossed the right/left boundary
((antennaLocationXDifference > 0) != (antinodeLocationXDifference > 0))
)
break;
antinodeLocationsMap[antennaType].Add(antinodeLocation);
} while (enableResonantHarmonics);
if(enableResonantHarmonics)
{
antinodeLocationsMap[antennaType].Add(antennaLocation1);
antinodeLocationsMap[antennaType].Add(antennaLocation2);
}
}
// adding to the overall antinode location set
overallAntinodeLocations = [.. overallAntinodeLocations, .. antinodeLocationsMap[antennaType]];
}
Int32 numberOfUniqueAntinodeLocations = overallAntinodeLocations.Count;
Console.WriteLine("numberOfUniqueAntinodeLocations = {0:d}", numberOfUniqueAntinodeLocations);
// to keep the console window from closing
Console.ReadKey();
}
}
}