Rule.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. using System.Text.RegularExpressions;
  2. namespace Day19;
  3. public partial class Rule
  4. {
  5. [GeneratedRegex(@"(\w)([<>])(\d+):(\w+)|(\w+)")]
  6. private partial Regex ItemMatch();
  7. private readonly IList<IRuleItem> _items;
  8. public Rule(string ruleText)
  9. {
  10. _items = ItemMatch().Matches(ruleText).Select<Match, IRuleItem>(m =>
  11. {
  12. if (m.Groups[5].Length > 0)
  13. {
  14. return new Terminal(m.Groups[5].Value);
  15. }
  16. return new Item(m.Groups[1].Value, m.Groups[2].Value, int.Parse(m.Groups[3].Value), m.Groups[4].Value);
  17. }).ToList();
  18. }
  19. public string Apply(Part p)
  20. {
  21. foreach (var item in _items)
  22. {
  23. //Console.WriteLine(item);
  24. var next = item.Apply(p);
  25. //Console.WriteLine($"=> {next}");
  26. if (next != null)
  27. {
  28. return next;
  29. }
  30. }
  31. throw new Exception("Rule should always match");
  32. }
  33. private interface IRuleItem
  34. {
  35. string? Apply(Part p);
  36. }
  37. private class Item : IRuleItem
  38. {
  39. private readonly string _property;
  40. private readonly string _op;
  41. private readonly int _value;
  42. private readonly string _next;
  43. public Item(string property, string op, int value, string next)
  44. {
  45. _property = property;
  46. _op = op;
  47. _value = value;
  48. _next = next;
  49. }
  50. public string? Apply(Part p)
  51. {
  52. if (_op == "<")
  53. {
  54. return p.Get(_property) < _value ? _next : null;
  55. }
  56. if (_op == ">")
  57. {
  58. return p.Get(_property) > _value ? _next : null;
  59. }
  60. return null;
  61. }
  62. public override string ToString()
  63. {
  64. return $"{_property} {_op} {_value} : {_next}";
  65. }
  66. }
  67. private class Terminal : IRuleItem
  68. {
  69. private readonly string _next;
  70. public Terminal(string next)
  71. {
  72. _next = next;
  73. }
  74. public string? Apply(Part p)
  75. {
  76. return _next;
  77. }
  78. public override string ToString()
  79. {
  80. return $"Terminal<{_next}>";
  81. }
  82. }
  83. }