AdventOfCode/AoC_2025/Day04.cs

103 lines
3.8 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.Linq;
using AdvenOfCode.Contracts;
using Coordinate = (int x, int y);
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
.Index()
.SelectMany(indexedLine => GetCoordinates(indexedLine.Item, indexedLine.Index))
.ToHashSet();
return coordinates;
}
private IEnumerable<Coordinate> GetCoordinates(string gridLine, int xIndex)
{
var indexedCharacters = gridLine.Index();
var validRolls = indexedCharacters.Where(tuple => tuple.Item == '@');
var rollCoordinates = validRolls.Select(tuple => (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 =
[
(-1, -1), (-1, 0), (-1, 1),
(0, -1), (0, 1),
(1, -1), (1, 0), (1, 1),
];
var possibleNeighbours = neighbourDirections
.Select(direction => (coordinate.x + direction.x, coordinate.y + direction.y));
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;
}
}