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(); 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 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(); var knownPatterns = new Dictionary(); 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 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> Towels, List Patterns) ParseInput() { var towels = new Dictionary>(); var patterns = new List(); 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); } }