Beispiel #1
0
        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("|")})");
        }
Beispiel #2
0
            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));
            }
Beispiel #3
0
        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;
            }));
        }
Beispiel #4
0
        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;
            }));
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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;
        }
Beispiel #7
0
 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));
 }
Beispiel #8
0
        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);
            }
        }