using System.Text.RegularExpressions; namespace Day19; public partial class Rule { [GeneratedRegex(@"(\w)([<>])(\d+):(\w+)|(\w+)")] private partial Regex ItemMatch(); private readonly IList _items; public Rule(string ruleText) { _items = ItemMatch().Matches(ruleText).Select(m => { if (m.Groups[5].Length > 0) { return new Terminal(m.Groups[5].Value); } return new Item(m.Groups[1].Value, m.Groups[2].Value, int.Parse(m.Groups[3].Value), m.Groups[4].Value); }).ToList(); } public string Apply(Part p) { foreach (var item in _items) { //Console.WriteLine(item); var next = item.Apply(p); //Console.WriteLine($"=> {next}"); if (next != null) { return next; } } throw new Exception("Rule should always match"); } private interface IRuleItem { string? Apply(Part p); } private class Item : IRuleItem { private readonly string _property; private readonly string _op; private readonly int _value; private readonly string _next; public Item(string property, string op, int value, string next) { _property = property; _op = op; _value = value; _next = next; } public string? Apply(Part p) { if (_op == "<") { return p.Get(_property) < _value ? _next : null; } if (_op == ">") { return p.Get(_property) > _value ? _next : null; } return null; } public override string ToString() { return $"{_property} {_op} {_value} : {_next}"; } } private class Terminal : IRuleItem { private readonly string _next; public Terminal(string next) { _next = next; } public string? Apply(Part p) { return _next; } public override string ToString() { return $"Terminal<{_next}>"; } } }