Files
AdventOfCode/Days/Day19.cs
2025-01-24 10:19:13 +01:00

179 lines
4.5 KiB
C#

using System.Collections.Frozen;
using System.Numerics;
using System.Runtime.Intrinsics.X86;
using Spectre.Console;
namespace AdventOfCode.Days;
public class Day19 : Day
{
public override int Number => 19;
public override string Name => "Linen Layout";
public override void RunPart1(bool display = true)
{
var (towels, patterns) = ParseInput();
var impossiblePatterns = new HashSet<string>();
var possiblePatterns = 0;
foreach (var pattern in patterns)
{
// Check if it's possible to make this pattern
if (CheckPattern(pattern))
{
possiblePatterns++;
}
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Number of designs that are possible: [yellow]{possiblePatterns}[/][/]");
}
return;
bool CheckPattern(ReadOnlySpan<char> pattern)
{
// Console.WriteLine($"Checking '{pattern}'");
if (pattern.Length is 0)
{
return true;
}
if (impossiblePatterns.Contains(pattern.ToString()))
{
return false;
}
var prefix = pattern[0];
if (!towels.TryGetValue(prefix, out var towelsList))
{
impossiblePatterns.Add(pattern.ToString());
return false;
}
foreach (var towel in towelsList)
{
if (pattern.StartsWith(towel) && CheckPattern(pattern[towel.Length..]))
{
return true;
}
}
impossiblePatterns.Add(pattern.ToString());
return false;
}
}
public override void RunPart2(bool display = true)
{
var (towels, patterns) = ParseInput();
var impossiblePatterns = new HashSet<string>();
var knownPatterns = new Dictionary<string, long>();
var possibleCombinations = 0L;
foreach (var pattern in patterns)
{
// Check if it's possible to make this pattern
possibleCombinations += CheckPattern(pattern);
}
if (display)
{
AnsiConsole.MarkupLine($"[green]Number of combinations that are possible: [yellow]{possibleCombinations}[/][/]");
}
return;
long CheckPattern(ReadOnlySpan<char> pattern)
{
if (pattern.Length is 0)
{
return 1;
}
if (impossiblePatterns.Contains(pattern.ToString()))
{
return 0;
}
if (knownPatterns.TryGetValue(pattern.ToString(), out var count))
{
return count;
}
var prefix = pattern[0];
if (!towels.TryGetValue(prefix, out var towelsList))
{
impossiblePatterns.Add(pattern.ToString());
return 0;
}
var possibilities = 0L;
foreach (var towel in towelsList)
{
if (pattern.StartsWith(towel))
{
possibilities += CheckPattern(pattern[towel.Length..]);
}
}
if (possibilities is 0)
{
impossiblePatterns.Add(pattern.ToString());
}
else
{
knownPatterns.Add(pattern.ToString(), possibilities);
}
return possibilities;
}
}
private (FrozenDictionary<char, List<string>> Towels, List<string> Patterns) ParseInput()
{
var towels = new Dictionary<char, List<string>>();
var patterns = new List<string>();
foreach (var line in Input.AsSpan().EnumerateLines())
{
if (towels.Count is 0)
{
var split = line.Split(", ");
foreach (var range in split)
{
var towel = line[range].Trim();
var prefix = towel[0];
if (!towels.TryGetValue(prefix, out var towelsList))
{
towelsList = [];
towels[prefix] = towelsList;
}
towelsList.Add(towel.ToString());
}
}
else if (!line.IsWhiteSpace())
{
var pattern = line.Trim();
patterns.Add(pattern.ToString());
}
}
return (towels.ToFrozenDictionary(), patterns);
}
}