AdventOfCode/AdventOfCode.Solutions/2023/Day 12/Day12.cs

77 lines
3.4 KiB
C#

namespace AdventOfCode.Solutions._2023
{
public partial class Day12 : IChallange
{
public int Year => 2023;
public int Day => 12;
private readonly InputReader _inputReader;
public Day12(InputReader inputReader)
{
_inputReader = inputReader;
_inputReader.SetInput(this);
}
public async Task<string> GetSolutionPart1()
{
long total = 0;
await foreach(string line in _inputReader.ReadAsStringLine())
{
string[] splitted = line.Split(' ');
int[] groups = splitted[1].Split(',').Select(int.Parse).ToArray();
long possiblies = Possibilities([], splitted[0], groups, 0, 0, 0);
total += possiblies;
}
return total.ToString();
}
public async Task<string> GetSolutionPart2()
{
long total = 0;
await foreach (string line in _inputReader.ReadAsStringLine())
{
string[] splitted = line.Split(' ');
var joinedLine = string.Join("?", [splitted[0], splitted[0], splitted[0], splitted[0], splitted[0]]);
int[] groups = splitted[1].Split(',').Select(int.Parse).ToArray();
int[] groupsTotal = groups.Concat(groups).Concat(groups).Concat(groups).Concat(groups).ToArray();
long possiblies = Possibilities([], joinedLine, groupsTotal, 0, 0, 0);
total += possiblies;
}
return total.ToString();
}
private static long Possibilities(Dictionary<(int, int, int), long> capturedCache, string stringToValidate, int[] captureGroups, int stringIndex, int groupIndex, int currentCaptureLength)
{
if (capturedCache.TryGetValue((stringIndex, groupIndex, currentCaptureLength), out var possibilities))
return possibilities;
if (stringIndex == stringToValidate.Length) // End of string
return groupIndex == captureGroups.Length || (groupIndex == captureGroups.Length - 1 && captureGroups[groupIndex] == currentCaptureLength) ? 1 : 0;
possibilities = 0L;
if (stringToValidate[stringIndex] is '.' or '?') // Assuming '?' is '.'
{
if (currentCaptureLength == 0) // Start a capture
{
possibilities += Possibilities(capturedCache, stringToValidate, captureGroups, stringIndex + 1, groupIndex, 0); // Not in capture. Skip to next char
}
else if (currentCaptureLength == captureGroups[groupIndex]) // After a capture
{
possibilities += Possibilities(capturedCache, stringToValidate, captureGroups, stringIndex + 1, groupIndex + 1, 0); // Captured group. Go to next group
}
}
if (stringToValidate[stringIndex] is '#' or '?' && groupIndex < captureGroups.Length && currentCaptureLength < captureGroups[groupIndex]) // Assuming '?' is '#'
{
possibilities += Possibilities(capturedCache, stringToValidate, captureGroups, stringIndex + 1, groupIndex, currentCaptureLength + 1); // In capture
}
// Add the capture to the capture cache
capturedCache[(stringIndex, groupIndex, currentCaptureLength)] = possibilities;
return possibilities;
}
}
}