103 lines
3.8 KiB
C#
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;
|
|
}
|
|
} |