AdventOfCode/AoC_2025/Day07.cs

130 lines
3.9 KiB
C#

using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using AdvenOfCode.Contracts;
using Coordinate = (int x, int y);
namespace AoC_2025;
public class Day07 : IPuzzleSolver<long>
{
private string[] ParsePuzzleInput(string path)
{
var puzzleInput = File.ReadAllLines(path)
.Where(line => !string.IsNullOrWhiteSpace(line))
.ToArray();
return puzzleInput;
}
public long SolvePart1(string pathToPuzzleInput)
{
var grid = ParsePuzzleInput(pathToPuzzleInput);
var start = GetStart(grid);
var count = TraverseGridAndCountSplitters(grid, start);
return count;
}
public long SolvePart2(string pathToPuzzleInput)
{
var grid = ParsePuzzleInput(pathToPuzzleInput);
var start = GetStart(grid);
var nodesWithCount = GetTimelinesCountRecursive(grid, start, []);
return nodesWithCount;
}
public long SolvePart2Again(string pathToPuzzleInput)
{
var grid = ParsePuzzleInput(pathToPuzzleInput);
var nodesWithCount = GetTimelinesCount(grid);
return nodesWithCount.Sum();
}
private Coordinate GetStart(string[] grid)
{
return (0, grid[0].IndexOf('S'));
}
private long TraverseGridAndCountSplitters(string[] grid, Coordinate start)
{
HashSet<Coordinate> visited = [start];
var seen = new Queue<Coordinate>();
seen.Enqueue(start);
var splittersHit = 0L;
while (seen.TryDequeue(out var current))
{
if (current.x >= grid.Length) continue;
if (current.y >= grid[0].Length || current.y < 0) continue;
if (grid[current.x][current.y] == '^')
{
splittersHit++;
CheckAndEnqueueIfNotVisited((current.x, current.y - 1));
CheckAndEnqueueIfNotVisited((current.x, current.y + 1));
}
else
{
CheckAndEnqueueIfNotVisited((current.x + 1, current.y));
}
}
return splittersHit;
void CheckAndEnqueueIfNotVisited(Coordinate coordinate)
{
if (visited.Add(coordinate)) seen.Enqueue(coordinate);
}
}
// Dictionary only for memoization
private long GetTimelinesCountRecursive(string[] grid, Coordinate current, Dictionary<Coordinate, long> memory)
{
if (current.x >= grid.Length)
{
return 1;
}
if(memory.TryGetValue(current, out var count)) return count;
if (grid[current.x][current.y] == '^')
{
var resLeft = GetTimelinesCountRecursive(grid, (current.x, current.y - 1), memory);
var resRight = GetTimelinesCountRecursive(grid, (current.x, current.y + 1), memory);
memory[current] = resLeft + resRight;
return resLeft + resRight;
}
var res = GetTimelinesCountRecursive(grid, (current.x + 1, current.y), memory);
memory[current] = res;
return res;
}
private long[] GetTimelinesCount(string[] grid)
{
var numbersGrid = grid
.Select(line => line.Select(c => 0L).ToArray())
.ToArray();
for (var x = 1; x < numbersGrid.Length; x++)
{
for (var y = 0; y < numbersGrid[x].Length; y++)
{
var gridValue = grid[x - 1][y];
switch (gridValue)
{
case 'S':
numbersGrid[x][y] = 1;
break;
case '.':
numbersGrid[x][y] += numbersGrid[x - 1][y];
break;
case '^':
numbersGrid[x][y - 1] += numbersGrid[x - 1][y];
numbersGrid[x][y + 1] += numbersGrid[x - 1][y];
break;
}
}
}
return numbersGrid[^1];
}
}