Files
Project-AOC-2024/Day8/Program.cs

196 lines
6.3 KiB
C#
Raw Normal View History

2024-12-08 12:40:24 +02:00
var lines = File.ReadAllLines("input.txt");
var charArray = new char[lines.Length, lines[0].Length];
for (var i = 0; i < charArray.GetLength(0); i++)
for (var j = 0; j < charArray.GetLength(1); j++)
{
charArray[i, j] = lines[i][j];
}
var uniqueCharacterPositions = GroupUniqueCharacterPositions(charArray);
var antinodeLocations = new List<(int, int)>();
var antinodeHarmonicsLocations = new List<(int, int)>();
foreach (var uniqueCharacter in uniqueCharacterPositions)
{
for (var i = 0; i < uniqueCharacter.Value.Count - 1; i++)
{
var currentPosition = uniqueCharacter.Value[i];
for (var j = i + 1; j < uniqueCharacter.Value.Count; j++)
{
var nextPosition = uniqueCharacter.Value[j];
if (Distance(currentPosition.Item1, currentPosition.Item2, nextPosition.Item1, nextPosition.Item2) >= 1)
{
antinodeLocations.AddRange(CalculateAntinodes(currentPosition, nextPosition, charArray));
}
antinodeHarmonicsLocations.AddRange(CalculateAntinodesWithHarmonics(currentPosition, nextPosition, charArray));
}
}
}
Console.WriteLine(
$"Part 1: {antinodeLocations.Distinct().Count()}\nPart 2: {antinodeHarmonicsLocations.Distinct().Count()}");
List<(int, int)> CalculateAntinodesWithHarmonics((int, int) currentPosition, (int, int) nextPosition, char[,] input)
{
var locations = new List<(int, int)>
{
currentPosition,
nextPosition
};
var verticalDistance = Math.Abs(currentPosition.Item1 - nextPosition.Item1);
var horizontalDistance = Math.Abs(currentPosition.Item2 - nextPosition.Item2);
var currentPositionClone = currentPosition;
var nextPositionClone = nextPosition;
int antinodePositionRow, antinodePositionColumn;
while (true)
{
if (currentPositionClone.Item1 < nextPositionClone.Item1)
{
antinodePositionRow = currentPositionClone.Item1 - verticalDistance;
}
else
{
antinodePositionRow = currentPositionClone.Item1 + verticalDistance;
}
if (currentPositionClone.Item2 < nextPositionClone.Item2)
{
antinodePositionColumn = currentPositionClone.Item2 - horizontalDistance;
}
else
{
antinodePositionColumn = currentPositionClone.Item2 + horizontalDistance;
}
if (IsValid(antinodePositionRow, antinodePositionColumn, input))
{
locations.Add((antinodePositionRow, antinodePositionColumn));
nextPositionClone = currentPositionClone;
currentPositionClone = (antinodePositionRow, antinodePositionColumn);
}
else
{
break;
}
}
currentPositionClone = currentPosition;
nextPositionClone = nextPosition;
while (true)
{
if (currentPositionClone.Item1 < nextPositionClone.Item1)
{
antinodePositionRow = nextPositionClone.Item1 + verticalDistance;
}
else
{
antinodePositionRow = nextPositionClone.Item1 - verticalDistance;
}
if (currentPositionClone.Item2 < nextPositionClone.Item2)
{
antinodePositionColumn = nextPositionClone.Item2 + horizontalDistance;
}
else
{
antinodePositionColumn = nextPositionClone.Item2 - horizontalDistance;
}
if (IsValid(antinodePositionRow, antinodePositionColumn, input))
{
locations.Add((antinodePositionRow, antinodePositionColumn));
currentPositionClone = nextPositionClone;
nextPositionClone = (antinodePositionRow, antinodePositionColumn);
}
else
{
break;
}
}
return locations;
}
List<(int, int)> CalculateAntinodes((int, int) currentPosition, (int, int) nextPosition, char[,] input)
{
var locations = new List<(int, int)>();
int firstAntinodePositionRow,
firstAntinodePositionColumn,
secondAntinodePositionRow,
secondAntinodePositionColumn;
var verticalDistance = Math.Abs(currentPosition.Item1 - nextPosition.Item1);
var horizontalDistance = Math.Abs(currentPosition.Item2 - nextPosition.Item2);
if (currentPosition.Item1 < nextPosition.Item1)
{
firstAntinodePositionRow = currentPosition.Item1 - verticalDistance;
secondAntinodePositionRow = nextPosition.Item1 + verticalDistance;
}
else
{
firstAntinodePositionRow = currentPosition.Item1 + verticalDistance;
secondAntinodePositionRow = nextPosition.Item1 - verticalDistance;
}
if (currentPosition.Item2 < nextPosition.Item2)
{
firstAntinodePositionColumn = currentPosition.Item2 - horizontalDistance;
secondAntinodePositionColumn = nextPosition.Item2 + horizontalDistance;
}
else
{
firstAntinodePositionColumn = currentPosition.Item2 + horizontalDistance;
secondAntinodePositionColumn = nextPosition.Item2 - horizontalDistance;
}
if (IsValid(firstAntinodePositionRow, firstAntinodePositionColumn, input))
{
locations.Add((firstAntinodePositionRow, firstAntinodePositionColumn));
}
if (IsValid(secondAntinodePositionRow, secondAntinodePositionColumn, input))
{
locations.Add((secondAntinodePositionRow, secondAntinodePositionColumn));
}
return locations;
}
Dictionary<char, List<(int, int)>> GroupUniqueCharacterPositions(char[,] array)
{
var charLocations = new Dictionary<char, List<(int, int)>>();
for (var i = 0; i < array.GetLength(0); i++)
{
for (var j = 0; j < array.GetLength(1); j++)
{
var currentChar = array[i, j];
if (currentChar == '.') continue;
if (!charLocations.ContainsKey(currentChar))
{
charLocations[currentChar] = new List<(int, int)>();
}
charLocations[currentChar].Add((i, j));
}
}
return charLocations;
}
bool IsValid(int row, int column, char[,] grid) => row >= 0 && row < grid.GetLength(0) && column >= 0 && column < grid.GetLength(1);
double Distance(int position1Row, int position1Column, int position2Row, int position2Column) => Math.Sqrt(Math.Pow(position1Column - position2Column, 2) + Math.Pow(position2Row - position1Row, 2));