static IRule CompileNodeForRule(string ruletext, Dictionary <int, RuleCacheItem> ruleSet) { Function Head, BuildingRule; Head = BuildingRule = new AndRule(); foreach (var item in ruletext.Split(' ')) { if (item.Contains("\"")) { var nodeToAdd = new StringRule { toMatch = item[1] };; //Comment this line for multi string rule support return(nodeToAdd); BuildingRule.AddNode(nodeToAdd); } else if (item.Contains("|")) { //Split on left and right Head = new OrRule(); Head.AddNode(BuildingRule); BuildingRule = new AndRule(); Head.AddNode(BuildingRule); } else { var childToExplore = int.Parse(item); //Check if the cached copy hasn't compiled yet and compile it if (ruleSet[childToExplore].CachedRule == null) { ruleSet[childToExplore].CachedRule = CompileNodeForRule(ruleSet[childToExplore].Text, ruleSet); } BuildingRule.AddNode(ruleSet[childToExplore].CachedRule); } } return(Head); }
static void Main(string[] args) { Dictionary <int, RuleCacheItem> ruleParse = new Dictionary <int, RuleCacheItem>(); List <string> toCheck = new List <string>(); foreach (var line in System.IO.File.ReadLines("puzzleinput.txt")) { if (line.Contains(':')) { var c = line.Split(':'); ruleParse.Add(int.Parse(c[0]), new RuleCacheItem { Text = c[1].Substring(1) }); } else if (!string.IsNullOrEmpty(line)) { toCheck.Add(line); } } //build tree var currentNode = ruleParse[0]; currentNode.CachedRule = CompileNodeForRule(currentNode.Text, ruleParse); int SuccessCount = toCheck.Count(line => currentNode.CachedRule.Match(0, line, 100).Any(t => t == line.Length)); Console.WriteLine($"Part 1: {SuccessCount}"); //Disgusting hack to replace nodes 8 and 11: var oldEight = ruleParse[8].CachedRule; //Update rule 8 ruleParse[8].CachedRule = new OrRule(); //LHS var lhs = new AndRule(); lhs.AddNode(ruleParse[42].CachedRule); //RHS var rhs = new AndRule(); rhs.AddNode(ruleParse[42].CachedRule); rhs.AddNode(ruleParse[8].CachedRule); ((Function)ruleParse[8].CachedRule).AddNode(lhs); ((Function)ruleParse[8].CachedRule).AddNode(rhs); //Update rule 11 var oldEleven = ruleParse[11].CachedRule; ruleParse[11].CachedRule = new OrRule(); //LHS lhs = new AndRule(); lhs.AddNode(ruleParse[42].CachedRule); lhs.AddNode(ruleParse[31].CachedRule); //RHS rhs = new AndRule(); rhs.AddNode(ruleParse[42].CachedRule); rhs.AddNode(ruleParse[11].CachedRule); rhs.AddNode(ruleParse[31].CachedRule); ((Function)ruleParse[11].CachedRule).AddNode(lhs); ((Function)ruleParse[11].CachedRule).AddNode(rhs); //Replace the old 8's and 11's with the new ones foreach (var node in ruleParse.Values) { if (typeof(Function).IsAssignableFrom(node.CachedRule.GetType())) { ((Function)node.CachedRule).ReplaceNode(oldEight, ruleParse[8].CachedRule); ((Function)node.CachedRule).ReplaceNode(oldEleven, ruleParse[11].CachedRule); } } SuccessCount = toCheck.Count(line => currentNode.CachedRule.Match(0, line, 100).Any(t => t == line.Length)); Console.WriteLine($"Part 2: {SuccessCount}"); Console.ReadLine(); }