179 lines
4.5 KiB
C#
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);
|
|
}
|
|
} |