private static string RulesToRegex(int startNode, Day19Input state) { var result = new List <string>(); var current = state.Rules[startNode]; foreach (var variant in current) { result.Add(variant.Select(v => { if (state.Lexes.TryGetValue(v, out var lex)) { return($"{lex}"); } return(RulesToRegex(v, state)); }).Join("")); } if (result.Count == 1) { return(result.First()); } return($"({result.Select(v => $"{v}").Join("|")})"); }
public Search Advance(char c, Day19Input state, out bool matched) { matched = false; var closed = new List <List <Frame> >(); var open = Stack.ToList(); while (open.Any()) { var frames = open.Shift(); var frame = frames.Pop(); var nextRule = frame.Variant[frame.NextRule]; frame = new Frame(frame.Variant, frame.NextRule + 1); if (state.Lexes.TryGetValue(nextRule, out var lex)) { if (lex != c) { continue; } while (frames.Any() && frame.NextRule >= frame.Variant.Count) { frame = frames.Pop(); } if (frame.NextRule < frame.Variant.Count) { closed.Add(frames.Append(frame).ToList()); continue; } matched = true; continue; } var nextVariants = state.Rules[nextRule]; foreach (var variant in nextVariants) { open.Add(frames.Append(frame).Append(new Frame(variant)).ToList()); } } return(new Search(closed)); }
private static long Run(Day19Input state) { return(state.Messages.Count(message => { var search = new Search(); while (message.Length > 0 && search.Stack.Any()) { var c = message[0]; message = message.Substring(1); search = search.Advance(c, state, out var matched); if (matched && message.Length == 0) { return true; } } return false; })); }
private static long Run(Day19Input state) { // Turn rules into regex //var regex = RulesToRegex(0, state.Nodes); var rx = new Dictionary <int, string>(); RulesToRegex2(0, state, new List <int>(), rx, new Dictionary <int, HashSet <int> >(), new HashSet <int>()); var regex = rx[0]; regex = $"^{regex}$"; return(state.Messages.Count(message => { var m = Regex.IsMatch(message, regex); if (!m) { Console.WriteLine(message); } return m; })); }
public static Day19Input ConvertInput(string input) { var result = new Day19Input(); var g = input.SplitOnBlankLines(); foreach (var line in g[0].SplitIntoLines()) { var m1 = RegexUtils.Deserialize(line, @"(?<name>\d+): (?<rule>.*)", new { name = 0, rule = "" }); var name = m1.name; var rule = m1.rule; CreateRule(result, name, rule); } foreach (var line in g[1].SplitIntoLines()) { result.Messages.Add(line.Trim()); } return(result); }
public static void CreateRule(Day19Input input, int name, string rules) { var result = new List <List <int> >(); var variants = rules.Split("|") .Select(group => group.Trim().Split(" ").Select(it => it.Trim()).ToList()) .ToList(); if (variants.Count == 1 && variants.First().Count == 1) { var item = variants.First().First(); if (Regex.IsMatch(item, @"""[ab]""")) { input.Lexes[name] = item[1]; return; } } foreach (var variant in variants) { var v = new List <int>(); result.Add(v); foreach (var item in variant) { if (Regex.IsMatch(item, @"\d+")) { v.Add(Convert.ToInt32(item)); } else { throw new ApplicationException(); } } } input.Rules[name] = result; }
private static long Run2(Day19Input state) { Day19a.CreateRule(state, 8, "42 | 42 8"); Day19a.CreateRule(state, 11, "42 31 | 42 11 31"); return(Run(state)); }
private static void RulesToRegex2(int node, Day19Input state, List <int> pathSoFar, Dictionary <int, string> regex, Dictionary <int, HashSet <int> > loops, HashSet <int> unresolved) { if (regex.ContainsKey(node)) { return; } if (state.Lexes.TryGetValue(node, out var lex)) { regex[node] = lex.ToString(); return; } pathSoFar = pathSoFar.ToList(); pathSoFar.Add(node); var result = new List <string>(); var variants = state.Rules[node]; if (node == 8) { variants = variants.Take(1).ToList(); } else if (node == 11) { variants = new List <List <int> > { new List <int> { 42, 31 } }; } foreach (var variant in variants) { foreach (var childNode in variant) { var loopIndex = pathSoFar.IndexOf(childNode); if (loopIndex != -1) { loops.Add(pathSoFar.Last(), childNode); continue; } RulesToRegex2(childNode, state, pathSoFar, regex, loops, unresolved); } var variantRegex = ""; bool tailRecursive = node == 8; var rules = variant.Select((it, index) => (it, index)).ToList(); if (node == 11) { var r42 = regex[42]; var r31 = regex[31]; for (int i = 1; i < 10; i++) { if (i > 1) { variantRegex += "|"; } variantRegex += "("; variantRegex += $"({r42}){{{i}}}"; variantRegex += $"({r31}){{{i}}}"; variantRegex += ")"; } variantRegex = $"({variantRegex})"; } else { foreach (var rule in rules) { var childNode = rule.it; if (!regex.ContainsKey(childNode)) { variantRegex += $"<{childNode}>"; unresolved.Add(childNode); continue; } var thisOne = regex[childNode]; if (loops.ContainsKey(childNode)) { variantRegex += $"({thisOne})*"; } else { variantRegex += $"{thisOne}"; } } if (tailRecursive) { variantRegex = $"({variantRegex})+"; } } result.Add(variantRegex); } if (result.Count == 1) { regex.Add(node, result.First()); } else { regex.Add(node, $"({result.Select(v => $"{v}").Join("|")})"); } if (unresolved.Contains(node)) { foreach (var key in regex.Keys.ToList()) { var k = $"<{node}>"; if (regex[key].Contains(k)) { if (loops.ContainsKey(node)) { regex[key] = regex[key].Replace(k, $"({regex[node]})*"); } else { regex[key] = regex[key].Replace(k, $"({regex[node]})"); } } } unresolved.Remove(node); } }