Program.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. namespace D20._1
  8. {
  9. class Program
  10. {
  11. public class Group
  12. {
  13. public int Id { get; set; }
  14. public int Level { get; set; }
  15. public string Str { get; set; }
  16. public List<Group> Groups { get; set; }
  17. public SortedSet<string> Possibilities { get; set; }
  18. public Group()
  19. {
  20. Groups = new List<Group>();
  21. Possibilities = new SortedSet<string>(new PC());
  22. Str = "";
  23. Id = 1;
  24. }
  25. }
  26. class PC : IComparer<string>
  27. {
  28. public int Compare(string x, string y) => y.Length.CompareTo(x.Length);
  29. }
  30. static IEnumerable<string> CombinePossibilities(string Str, List<Group> children, int depth = 0)
  31. {
  32. if (depth == children.Count) { yield return Str; yield break; }
  33. var child = children[depth];
  34. foreach (var prevchildPossibility in child.Possibilities)
  35. foreach (var t in CombinePossibilities(Str.Replace(("(" + (char)child.Id + ")").ToString(), prevchildPossibility), children, depth + 1))
  36. {
  37. if (Str.Contains(((char)child.Id).ToString()) == false) throw new Exception();
  38. yield return t;
  39. }
  40. }
  41. static Group BuildGroups(int level, string priority, string regex, int index)
  42. {
  43. if (index >= regex.Length) return null;
  44. var group = new Group() { Level = level, Str = "" };
  45. bool capture = true;
  46. while (
  47. index < regex.Length &&
  48. priority[index] >= level)
  49. {
  50. if (priority[index] > level && capture)
  51. {
  52. capture = false;
  53. var childGroup = BuildGroups(level + 1, priority, regex, index);
  54. if (childGroup != null)
  55. {
  56. childGroup.Id = group.Groups.Count + 1;
  57. group.Str += "(" + (char)childGroup.Id;
  58. group.Groups.Add(childGroup);
  59. }
  60. }
  61. else if (priority[index] == level)
  62. {
  63. capture = true;
  64. group.Str += regex[index];
  65. }
  66. index++;
  67. }
  68. if (index < regex.Length) group.Str += regex[index];
  69. return group;
  70. }
  71. static void Test(Group root)
  72. {
  73. IEnumerable<string> possibilities;
  74. if (root.Groups.Count == 0)
  75. {
  76. var splittedPossibilities = root.Str.TrimStart('(').TrimEnd(')').Split("|");
  77. foreach (var splittedPossibility in splittedPossibilities) root.Possibilities.Add(splittedPossibility);
  78. return;
  79. }
  80. foreach (var group in root.Groups) Test(group);
  81. possibilities = CombinePossibilities(root.Str, root.Groups);
  82. foreach (var possibility in possibilities)
  83. {
  84. var splittedPossibilities = possibility.TrimStart('(').TrimEnd(')').Split("|");
  85. foreach (var splittedPossibility in splittedPossibilities) root.Possibilities.Add(splittedPossibility);
  86. }
  87. }
  88. static void Main(string[] args)
  89. {
  90. if (args.Length < 1) return;
  91. if (File.Exists(args[0]) == false) return;
  92. var file = File.OpenText(args[0]);
  93. var regex = file.ReadToEnd();
  94. file.Close();
  95. //regex = @"^ENNWSWW(NEWS|)SSSEEN(WNSE|)EE(SWEN|)NNN$";
  96. //regex = @"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$";
  97. //regex = @"^N(EEENWWW|N)$";
  98. regex = regex.TrimStart('^').TrimEnd('$');
  99. int par = 0, maxpar = 0;
  100. var priority = "";
  101. for (var i = 0; i < regex.Length; ++i)
  102. {
  103. if (regex[i] == '(')
  104. {
  105. par++;
  106. if (par > maxpar) maxpar = par;
  107. }
  108. if (regex[i] == ')') par--;
  109. priority += (char)par;
  110. }
  111. var root = BuildGroups(0, priority, regex, 0);
  112. var sw = Stopwatch.StartNew();
  113. Test(root);
  114. sw.Stop();
  115. Console.WriteLine(sw.ElapsedMilliseconds);
  116. Dictionary<(int x, int y), int> positions = new Dictionary<(int x, int y), int>();
  117. foreach (var path in root.Possibilities)
  118. {
  119. TestResult(path, positions);
  120. }
  121. int max = positions.Max(p => p.Value);
  122. Console.WriteLine(max);
  123. }
  124. private static void TestResult(string str, Dictionary<(int x, int y), int> positions)
  125. {
  126. (int x, int y) pos = (0, 0);
  127. int dist = 0;
  128. positions.TryAdd(pos, 0);
  129. foreach (var c in str)
  130. {
  131. var bpos = pos;
  132. switch (c)
  133. {
  134. case 'N': pos.y -= 1; break;
  135. case 'S': pos.y += 1; break;
  136. case 'W': pos.x -= 1; break;
  137. case 'E': pos.x += 1; break;
  138. }
  139. dist++;
  140. if (positions.TryAdd(pos, dist) == false)
  141. dist = Math.Min(dist + 1, positions[pos]);
  142. positions[pos] = dist;
  143. }
  144. }
  145. }
  146. }