Переглянути джерело

Better algo but answer is false pour given input

bastien.monsarrat 6 роки тому
батько
коміт
68c79e3567
1 змінених файлів з 109 додано та 61 видалено
  1. 109 61
      D20.1/Program.cs

+ 109 - 61
D20.1/Program.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Text.RegularExpressions;
@@ -8,6 +9,55 @@ namespace D20._1
 {
     class Program
     {
+        public class Group
+        {
+            public int Level { get; set; }
+            public string Str { get; set; }
+            public List<Group> Groups { get; set; }
+            public Group() => Groups = new List<Group>();
+        }
+
+        static IEnumerable<string> CombinePossibilities(string Str, List<(string, IEnumerable<string>)> prev, int depth = 0)
+        {
+            if (depth == prev.Count) { yield return Str; yield break; }
+
+            var prevStr = prev[depth];
+
+            foreach (var prevPos in prevStr.Item2)
+                foreach (var t in CombinePossibilities(Str.Replace(prevStr.Item1, prevPos), prev, depth + 1))
+                    yield return t;
+        }
+
+        static Group Test(int level, string priority, string regex, int index)
+        {
+            if (index >= regex.Length) return null;
+
+            var group = new Group() { Level = level, Str = "" };
+
+            bool capture = true;
+
+            while (
+                index < regex.Length &&
+                priority[index] >= level)
+            {
+                if (priority[index] > level && capture)
+                {
+                    capture = false;
+                    var childGroup = Test(level + 1, priority, regex, index);
+                    if (childGroup != null) group.Groups.Add(childGroup);
+                }
+                else if (priority[index] == level)
+                    capture = true;
+
+                group.Str += regex[index];
+
+                index++;
+            }
+            if (index < regex.Length) group.Str += regex[index];
+
+            return group;
+        }
+
         static void Main(string[] args)
         {
             if (args.Length < 1) return;
@@ -17,90 +67,88 @@ namespace D20._1
             var regex = file.ReadToEnd();
             file.Close();
 
-            //regex = @"^E(N|S(E|N))ES$";
-            regex = @"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$";
+            //regex = @"^E(N|S(E|N)(W|S)SE)ES$";
+            //regex = @"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$";
 
-            List<int> result = new List<int>();
-            var str = regex.TrimStart('^').TrimEnd('$');
-
-            var allPath = RunPath(str, result);
-            int max = 0;
-            foreach (var path in allPath)
+            int par = 0, maxpar = 0;
+            var priority = "";
+            for (var i = 0; i < regex.Length; ++i)
             {
-                var r = GetResult(path);
-                if (r > max) max = r;
+                if (regex[i] == '(')
+                {
+                    par++;
+                    if (par > maxpar) maxpar = par;
+                }
+                if (regex[i] == ')') par--;
+                priority += (char)par;
             }
 
-            Console.WriteLine(max);
-        }
+            //var tt = Test(0, priority, regex, 0);
 
-        private static IEnumerable<string> RunPath(string str, List<int> result)
-        {
-            bool hasParenthesis = false;
-            int minLength = 0, minIndex = 0;
+            Stack<(int, Group)> groups = new Stack<(int, Group)>();
+            groups.Push((0, new Group() { Level = 0, Str = regex }));
 
-            int par = 0, index = 0;
-            List<int> pipes = new List<int>();
-            foreach (var c in str)
+            for (var level = 1; level <= maxpar; ++level)
             {
-                if (c == '(') par++;
-                if (c == ')')
+                Group cur = new Group() { Level = level, Str = "" };
+                for (var i = 1; i < regex.Length; ++i)
                 {
-                    par--;
-                    if (par == 0) break;
-                }
+                    if (priority[i] >= level) cur.Str += regex[i];
 
-                if (par == 1 && c == '|')
-                {
-                    pipes.Add(index);
+                    if (priority[i] < level && priority[i - 1] >= level)
+                    {
+                        cur.Str += regex[i];
+                        groups.Push((level, cur));
+                        cur = new Group() { Level = level, Str = "" };
+                    }
                 }
+            }
 
-                if (hasParenthesis == false && par == 1)
-                {
-                    minIndex = index;
-                    hasParenthesis = true;
-                }
+            var prevm1 = new List<(string, IEnumerable<string>)>();
 
-                if (par != 0) minLength++;
+            var sw = Stopwatch.StartNew();
 
-                index++;
-            }
+            for (var level = maxpar; level >= 0; --level)
+            {
+                HashSet<string> all = new HashSet<string>();
+                while (groups.Count > 0 && groups.Peek().Item1 == level)
+                    all.Add(groups.Pop().Item2.Str);
 
-            if (pipes.Count == 0)
-                return new[] { str };
+                var prev = new List<(string, IEnumerable<string>)>(prevm1);
 
-            var possibilitiesStr = "";
-            if (hasParenthesis)
-                possibilitiesStr = str.Substring(minIndex + 1, minLength - 1);
-            else
-                possibilitiesStr = str.Substring(minIndex, minLength);
+                prevm1.Clear();
+                foreach (var a in all)
+                {
+                    var possibilities = new HashSet<string>();
 
-            List<string> possibilities = new List<string>();
+                    var list = prev.Where(p => a.Contains(p.Item1)).ToList();
 
-            int beforePipe = minIndex;
-            for (var i = 0; i < pipes.Count; ++i)
-            {
-                possibilities.Add(possibilitiesStr.Substring(beforePipe - minIndex, pipes[i] - beforePipe - 1));
-                beforePipe = pipes[0];
+                    var res = CombinePossibilities(a, list);
+
+                    foreach (var pp in res)
+                    {
+                        var ppp = pp.TrimStart('(').TrimEnd(')').Split("|");
+                        foreach (var pppp in ppp) possibilities.Add(pppp);
+                    }
+
+                    prevm1.Add((a, possibilities));
+                }
             }
-            possibilities.Add(possibilitiesStr.Substring(beforePipe - minIndex));
 
-            List<string> results = new List<string>();
-            foreach (var possibility in possibilities)
-            {
-                var rr = RunPath(possibility, result);
+            sw.Stop();
 
-                foreach (var r in rr)
-                {
-                    var nr = str.Substring(0, minIndex) + r + str.Substring(minIndex + minLength + 1);
+            Console.WriteLine(sw.ElapsedMilliseconds);
 
-                    var rs = RunPath(nr, result);
-                    foreach (var s in rs)
-                    results.Add(s);
-                }
+            List<int> result = new List<int>();
+            
+            int max = 0;
+            foreach (var path in prevm1.First().Item2)
+            {
+                var r = GetResult(path);
+                if (r > max) max = r;
             }
 
-            return results;
+            Console.WriteLine(max);
         }
 
         private static int GetResult(string str)