1
0

Program.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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 Level { get; set; }
  14. public string Str { get; set; }
  15. public List<Group> Groups { get; set; }
  16. public Group() => Groups = new List<Group>();
  17. }
  18. static IEnumerable<string> CombinePossibilities(string Str, List<(string, IEnumerable<string>)> prev, int depth = 0)
  19. {
  20. if (depth == prev.Count) { yield return Str; yield break; }
  21. var prevStr = prev[depth];
  22. foreach (var prevPos in prevStr.Item2)
  23. foreach (var t in CombinePossibilities(Str.Replace(prevStr.Item1, prevPos), prev, depth + 1))
  24. yield return t;
  25. }
  26. static Group Test(int level, string priority, string regex, int index)
  27. {
  28. if (index >= regex.Length) return null;
  29. var group = new Group() { Level = level, Str = "" };
  30. bool capture = true;
  31. while (
  32. index < regex.Length &&
  33. priority[index] >= level)
  34. {
  35. if (priority[index] > level && capture)
  36. {
  37. capture = false;
  38. var childGroup = Test(level + 1, priority, regex, index);
  39. if (childGroup != null) group.Groups.Add(childGroup);
  40. }
  41. else if (priority[index] == level)
  42. capture = true;
  43. group.Str += regex[index];
  44. index++;
  45. }
  46. if (index < regex.Length) group.Str += regex[index];
  47. return group;
  48. }
  49. static void Main(string[] args)
  50. {
  51. if (args.Length < 1) return;
  52. if (File.Exists(args[0]) == false) return;
  53. var file = File.OpenText(args[0]);
  54. var regex = file.ReadToEnd();
  55. file.Close();
  56. //regex = @"^E(N|S(E|N)(W|S)SE)ES$";
  57. //regex = @"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$";
  58. int par = 0, maxpar = 0;
  59. var priority = "";
  60. for (var i = 0; i < regex.Length; ++i)
  61. {
  62. if (regex[i] == '(')
  63. {
  64. par++;
  65. if (par > maxpar) maxpar = par;
  66. }
  67. if (regex[i] == ')') par--;
  68. priority += (char)par;
  69. }
  70. //var tt = Test(0, priority, regex, 0);
  71. Stack<(int, Group)> groups = new Stack<(int, Group)>();
  72. groups.Push((0, new Group() { Level = 0, Str = regex }));
  73. for (var level = 1; level <= maxpar; ++level)
  74. {
  75. Group cur = new Group() { Level = level, Str = "" };
  76. for (var i = 1; i < regex.Length; ++i)
  77. {
  78. if (priority[i] >= level) cur.Str += regex[i];
  79. if (priority[i] < level && priority[i - 1] >= level)
  80. {
  81. cur.Str += regex[i];
  82. groups.Push((level, cur));
  83. cur = new Group() { Level = level, Str = "" };
  84. }
  85. }
  86. }
  87. var prevm1 = new List<(string, IEnumerable<string>)>();
  88. var sw = Stopwatch.StartNew();
  89. for (var level = maxpar; level >= 0; --level)
  90. {
  91. HashSet<string> all = new HashSet<string>();
  92. while (groups.Count > 0 && groups.Peek().Item1 == level)
  93. all.Add(groups.Pop().Item2.Str);
  94. var prev = new List<(string, IEnumerable<string>)>(prevm1);
  95. prevm1.Clear();
  96. foreach (var a in all)
  97. {
  98. var possibilities = new HashSet<string>();
  99. var list = prev.Where(p => a.Contains(p.Item1)).ToList();
  100. var res = CombinePossibilities(a, list);
  101. foreach (var pp in res)
  102. {
  103. var ppp = pp.TrimStart('(').TrimEnd(')').Split("|");
  104. foreach (var pppp in ppp) possibilities.Add(pppp);
  105. }
  106. prevm1.Add((a, possibilities));
  107. }
  108. }
  109. sw.Stop();
  110. Console.WriteLine(sw.ElapsedMilliseconds);
  111. List<int> result = new List<int>();
  112. int max = 0;
  113. foreach (var path in prevm1.First().Item2)
  114. {
  115. var r = GetResult(path);
  116. if (r > max) max = r;
  117. }
  118. Console.WriteLine(max);
  119. }
  120. private static int GetResult(string str)
  121. {
  122. (int x, int y) pos = (0, 0);
  123. HashSet<((int x, int y) from, (int x, int y) to)> doors = new HashSet<((int x, int y) from, (int x, int y) to)>();
  124. foreach (var c in str)
  125. {
  126. var bpos = pos;
  127. switch (c)
  128. {
  129. case 'N': pos.y -= 1; break;
  130. case 'S': pos.y += 1; break;
  131. case 'W': pos.x -= 1; break;
  132. case 'E': pos.x += 1; break;
  133. }
  134. doors.Add((bpos, pos));
  135. doors.Add((pos, bpos));
  136. }
  137. return GetBreadthFirstSearch(doors, pos);
  138. }
  139. // https://en.wikipedia.org/wiki/Breadth-first_search
  140. private static int GetBreadthFirstSearch(HashSet<((int x, int y) from, (int x, int y) to)> doors, (int x, int y) togo)
  141. {
  142. var nodesToVisit = new Queue<(int x, int y)>();
  143. var visitedNodes = new HashSet<(int x, int y)>();
  144. var meta = new Dictionary<(int x, int y), (int x, int y)>()
  145. {
  146. { (0, 0), (0, 0) }
  147. };
  148. nodesToVisit.Enqueue((0, 0));
  149. while (nodesToVisit.Count > 0)
  150. {
  151. var node = nodesToVisit.Dequeue();
  152. // Found it!
  153. if (node == togo)
  154. {
  155. var count = GetActionList(togo, meta, node);
  156. return count;
  157. }
  158. foreach ((int mx, int my) mv in new []{ (0, -1), (1, 0), (0, 1), (-1, 0) })
  159. {
  160. (int x, int y) successor = (node.x + mv.mx, node.y + mv.my);
  161. // Continue if no door exist
  162. if (doors.Contains((node, successor)) == false) continue;
  163. if (visitedNodes.Contains(successor)) continue;
  164. if (nodesToVisit.Contains(successor) == false)
  165. {
  166. meta.TryAdd(successor, mv);
  167. nodesToVisit.Enqueue(successor);
  168. }
  169. }
  170. visitedNodes.Add(node);
  171. }
  172. return -1;
  173. }
  174. private static int GetActionList((int x, int y) root, Dictionary<(int x, int y), (int x, int y)> meta, (int x, int y) node)
  175. {
  176. var actionList = new List<(int x, int y)>();
  177. while (meta[node] != (0, 0))
  178. {
  179. var action = meta[node];
  180. node = (node.x - action.x, node.y - action.y);
  181. actionList.Add(action);
  182. }
  183. return actionList.Count;
  184. }
  185. }
  186. }