|
|
@@ -11,24 +11,40 @@ namespace D20._1
|
|
|
{
|
|
|
public class Group
|
|
|
{
|
|
|
+ public int Id { get; set; }
|
|
|
public int Level { get; set; }
|
|
|
public string Str { get; set; }
|
|
|
public List<Group> Groups { get; set; }
|
|
|
- public Group() => Groups = new List<Group>();
|
|
|
+ public SortedSet<string> Possibilities { get; set; }
|
|
|
+ public Group()
|
|
|
+ {
|
|
|
+ Groups = new List<Group>();
|
|
|
+ Possibilities = new SortedSet<string>(new PC());
|
|
|
+ Str = "";
|
|
|
+ Id = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ class PC : IComparer<string>
|
|
|
+ {
|
|
|
+ public int Compare(string x, string y) => y.Length.CompareTo(x.Length);
|
|
|
}
|
|
|
|
|
|
- static IEnumerable<string> CombinePossibilities(string Str, List<(string, IEnumerable<string>)> prev, int depth = 0)
|
|
|
+ static IEnumerable<string> CombinePossibilities(string Str, List<Group> children, int depth = 0)
|
|
|
{
|
|
|
- if (depth == prev.Count) { yield return Str; yield break; }
|
|
|
+ if (depth == children.Count) { yield return Str; yield break; }
|
|
|
|
|
|
- var prevStr = prev[depth];
|
|
|
+ var child = children[depth];
|
|
|
|
|
|
- foreach (var prevPos in prevStr.Item2)
|
|
|
- foreach (var t in CombinePossibilities(Str.Replace(prevStr.Item1, prevPos), prev, depth + 1))
|
|
|
+ foreach (var prevchildPossibility in child.Possibilities)
|
|
|
+ foreach (var t in CombinePossibilities(Str.Replace(("(" + (char)child.Id + ")").ToString(), prevchildPossibility), children, depth + 1))
|
|
|
+ {
|
|
|
+ if (Str.Contains(((char)child.Id).ToString()) == false) throw new Exception();
|
|
|
yield return t;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- static Group Test(int level, string priority, string regex, int index)
|
|
|
+ static Group BuildGroups(int level, string priority, string regex, int index)
|
|
|
{
|
|
|
if (index >= regex.Length) return null;
|
|
|
|
|
|
@@ -43,21 +59,50 @@ namespace D20._1
|
|
|
if (priority[index] > level && capture)
|
|
|
{
|
|
|
capture = false;
|
|
|
- var childGroup = Test(level + 1, priority, regex, index);
|
|
|
- if (childGroup != null) group.Groups.Add(childGroup);
|
|
|
+ var childGroup = BuildGroups(level + 1, priority, regex, index);
|
|
|
+ if (childGroup != null)
|
|
|
+ {
|
|
|
+ childGroup.Id = group.Groups.Count + 1;
|
|
|
+
|
|
|
+ group.Str += "(" + (char)childGroup.Id;
|
|
|
+ group.Groups.Add(childGroup);
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
else if (priority[index] == level)
|
|
|
+ {
|
|
|
capture = true;
|
|
|
-
|
|
|
- group.Str += regex[index];
|
|
|
+ group.Str += regex[index];
|
|
|
+ }
|
|
|
|
|
|
index++;
|
|
|
}
|
|
|
+
|
|
|
if (index < regex.Length) group.Str += regex[index];
|
|
|
|
|
|
return group;
|
|
|
}
|
|
|
|
|
|
+ static void Test(Group root)
|
|
|
+ {
|
|
|
+ IEnumerable<string> possibilities;
|
|
|
+ if (root.Groups.Count == 0)
|
|
|
+ {
|
|
|
+ var splittedPossibilities = root.Str.TrimStart('(').TrimEnd(')').Split("|");
|
|
|
+ foreach (var splittedPossibility in splittedPossibilities) root.Possibilities.Add(splittedPossibility);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var group in root.Groups) Test(group);
|
|
|
+
|
|
|
+ possibilities = CombinePossibilities(root.Str, root.Groups);
|
|
|
+ foreach (var possibility in possibilities)
|
|
|
+ {
|
|
|
+ var splittedPossibilities = possibility.TrimStart('(').TrimEnd(')').Split("|");
|
|
|
+ foreach (var splittedPossibility in splittedPossibilities) root.Possibilities.Add(splittedPossibility);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
static void Main(string[] args)
|
|
|
{
|
|
|
if (args.Length < 1) return;
|
|
|
@@ -67,9 +112,11 @@ namespace D20._1
|
|
|
var regex = file.ReadToEnd();
|
|
|
file.Close();
|
|
|
|
|
|
- //regex = @"^E(N|S(E|N)(W|S)SE)ES$";
|
|
|
- //regex = @"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$";
|
|
|
+ //regex = @"^ENNWSWW(NEWS|)SSSEEN(WNSE|)EE(SWEN|)NNN$";
|
|
|
+ regex = @"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$";
|
|
|
+ //regex = @"^N(EEENWWW|N)$";
|
|
|
|
|
|
+ regex = regex.TrimStart('^').TrimEnd('$');
|
|
|
int par = 0, maxpar = 0;
|
|
|
var priority = "";
|
|
|
for (var i = 0; i < regex.Length; ++i)
|
|
|
@@ -83,66 +130,18 @@ namespace D20._1
|
|
|
priority += (char)par;
|
|
|
}
|
|
|
|
|
|
- //var tt = Test(0, priority, regex, 0);
|
|
|
-
|
|
|
- Stack<(int, Group)> groups = new Stack<(int, Group)>();
|
|
|
- groups.Push((0, new Group() { Level = 0, Str = regex }));
|
|
|
-
|
|
|
- for (var level = 1; level <= maxpar; ++level)
|
|
|
- {
|
|
|
- Group cur = new Group() { Level = level, Str = "" };
|
|
|
- for (var i = 1; i < regex.Length; ++i)
|
|
|
- {
|
|
|
- if (priority[i] >= level) cur.Str += regex[i];
|
|
|
-
|
|
|
- if (priority[i] < level && priority[i - 1] >= level)
|
|
|
- {
|
|
|
- cur.Str += regex[i];
|
|
|
- groups.Push((level, cur));
|
|
|
- cur = new Group() { Level = level, Str = "" };
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- var prevm1 = new List<(string, IEnumerable<string>)>();
|
|
|
+ var root = BuildGroups(0, priority, regex, 0);
|
|
|
|
|
|
var sw = Stopwatch.StartNew();
|
|
|
|
|
|
- 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);
|
|
|
-
|
|
|
- var prev = new List<(string, IEnumerable<string>)>(prevm1);
|
|
|
-
|
|
|
- prevm1.Clear();
|
|
|
- foreach (var a in all)
|
|
|
- {
|
|
|
- var possibilities = new HashSet<string>();
|
|
|
-
|
|
|
- var list = prev.Where(p => a.Contains(p.Item1)).ToList();
|
|
|
-
|
|
|
- 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));
|
|
|
- }
|
|
|
- }
|
|
|
+ Test(root);
|
|
|
|
|
|
sw.Stop();
|
|
|
|
|
|
Console.WriteLine(sw.ElapsedMilliseconds);
|
|
|
|
|
|
- List<int> result = new List<int>();
|
|
|
-
|
|
|
int max = 0;
|
|
|
- foreach (var path in prevm1.First().Item2)
|
|
|
+ foreach (var path in root.Possibilities)
|
|
|
{
|
|
|
var r = GetResult(path);
|
|
|
if (r > max) max = r;
|