AdventOfCode/AoC_2025/Day04.cs

99 lines
3.7 KiB
C#

using AdvenOfCode.Contracts;
using AdventOfCode.HelperClasses;
namespace AoC_2025;
public class Day04 : IPuzzleSolver<long>
{
private string[] ParsePuzzleInput(string path)
{
var puzzleInput = File.ReadAllLines(path)
.Where(line => !string.IsNullOrWhiteSpace(line))
.Select(line => line.Trim())
.ToArray();
return puzzleInput;
}
public long SolvePart1(string pathToPuzzleInput)
{
var paperrollGrid = ParsePuzzleInput(pathToPuzzleInput);
var accessiblePaperrolls = GetAccessiblePaperrolls(paperrollGrid);
var countAccessibleRolls = accessiblePaperrolls.Count();
return countAccessibleRolls;
}
public long SolvePart2(string pathToPuzzleInput)
{
var paperrollGrid = ParsePuzzleInput(pathToPuzzleInput);
var rollCoordinates = GetRollCoordinates(paperrollGrid);
var countAccessibleRolls = RecursiveCountAllRemovableRolls(rollCoordinates);
return countAccessibleRolls;
}
private IEnumerable<Coordinate> GetAccessiblePaperrolls(IEnumerable<string> paperrollGrid)
{
var rollCoordinates = GetRollCoordinates(paperrollGrid);
var rollsWithNeighbours = GetNeighbours(rollCoordinates);
var accessiblePaperrolls = FilterForLessThan(rollsWithNeighbours, 4);
return accessiblePaperrolls;
}
private int RecursiveCountAllRemovableRolls(HashSet<Coordinate> coordinates)
{
var rollsWithNeighbours = GetNeighbours(coordinates);
var accessiblePaperrolls = FilterForLessThan(rollsWithNeighbours, 4).ToArray();
var countAccessibleRolls = accessiblePaperrolls.Length;
coordinates.ExceptWith(accessiblePaperrolls);
return countAccessibleRolls == 0
? 0
: countAccessibleRolls + RecursiveCountAllRemovableRolls(coordinates);
}
private HashSet<Coordinate> GetRollCoordinates(IEnumerable<string> paperrollGrid)
{
var coordinates = paperrollGrid
.SelectMany((line, xIndex) => GetRollCoordinates(line, xIndex))
.ToHashSet();
return coordinates;
}
private IEnumerable<Coordinate> GetRollCoordinates(string gridLine, int xIndex)
{
var indexedCharacters = gridLine.Index();
var validRolls = indexedCharacters.Where(tuple => tuple.Item == '@');
var rollCoordinates = validRolls.Select(tuple => new Coordinate(xIndex, tuple.Index));
return rollCoordinates;
}
private IEnumerable<(Coordinate coordinate, Coordinate[] neighbours)> GetNeighbours(HashSet<Coordinate> rollCoordinates)
{
var coordsWithNeighbourCount = rollCoordinates
.Select(coord => (coord, GetNeighbours(coord, rollCoordinates)));
return coordsWithNeighbourCount;
}
private Coordinate[] GetNeighbours(Coordinate coordinate, HashSet<Coordinate> coordinates)
{
Coordinate[] neighbourDirections =
[
new(-1, -1), new(-1, 0), new(-1, 1),
new(0, -1), new(0, 1),
new(1, -1), new(1, 0), new(1, 1),
];
var possibleNeighbours = neighbourDirections
.Select(direction => coordinate + direction);
var actualNeighbours = possibleNeighbours
.Where(coord => coordinates.Contains(coord))
.ToArray();
return actualNeighbours;
}
private IEnumerable<Coordinate> FilterForLessThan(IEnumerable<(Coordinate coordinate, Coordinate[] neighbours)> coordinatesWithNeighbours,
int lessThan)
{
var coordinatesWithLess = coordinatesWithNeighbours
.Where(roll => roll.neighbours.Length < lessThan)
.Select(roll => roll.coordinate);
return coordinatesWithLess;
}
}