|
|
@@ -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)
|