Day 19 - Linen Layout
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
C#
Part 2 was pretty much the same as Part 2 except we can’t short-circuit when we find the first match. So, implement a cache of each sub-pattern and the number of ways to form it from the towels, and things get much faster.
using System.Collections.Immutable; using System.Diagnostics; using Common; namespace Day19; static class Program { static void Main() { var start = Stopwatch.GetTimestamp(); var sampleInput = ReceiveInput("sample.txt"); var programInput = ReceiveInput("input.txt"); Console.WriteLine($"Part 1 sample: {Part1(sampleInput)}"); Console.WriteLine($"Part 1 input: {Part1(programInput)}"); Console.WriteLine($"Part 2 sample: {Part2(sampleInput)}"); Console.WriteLine($"Part 2 input: {Part2(programInput)}"); Console.WriteLine($"That took about {Stopwatch.GetElapsedTime(start)}"); } static object Part1(Input input) { return input.Patterns .Select(p => AnyTowelMatches(p, input.Towels) ? 1 : 0) .Sum(); } static object Part2(Input input) { var matchCache = new Dictionary<string, long>(); return input.Patterns .Select(p => CountTowelMatches(p, input.Towels, matchCache)) .Sum(); } private static bool AnyTowelMatches( string pattern, ImmutableArray<string> towels) { return towels .Where(t => t.Length <= pattern.Length) .Select(t => !pattern.StartsWith(t) ? false : (pattern.Length == t.Length) ? true : AnyTowelMatches(pattern.Substring(t.Length), towels)) .Any(r => r); } private static long CountTowelMatches( string pattern, ImmutableArray<string> towels, Dictionary<string, long> matchCache) { if (matchCache.TryGetValue(pattern, out var count)) return count; count = towels .Where(t => t.Length <= pattern.Length) .Select(t => !pattern.StartsWith(t) ? 0 : (pattern.Length == t.Length) ? 1 : CountTowelMatches(pattern.Substring(t.Length), towels, matchCache)) .Sum(); matchCache[pattern] = count; return count; } static Input ReceiveInput(string file) { using var reader = new StreamReader(file); var towels = reader.ReadLine()!.SplitAndTrim(',').ToImmutableArray(); var patterns = new List<string>(); reader.ReadLine(); var line = reader.ReadLine(); while (line is not null) { patterns.Add(line); line = reader.ReadLine(); } return new Input() { Towels = towels, Patterns = [..patterns], }; } public class Input { public required ImmutableArray<string> Towels { get; init; } public required ImmutableArray<string> Patterns { get; init; } } }