1
0

Program.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text.RegularExpressions;
  6. namespace D20._1
  7. {
  8. class Program
  9. {
  10. static void Main(string[] args)
  11. {
  12. if (args.Length < 1) return;
  13. if (File.Exists(args[0]) == false) return;
  14. var file = File.OpenText(args[0]);
  15. var regex = file.ReadToEnd();
  16. file.Close();
  17. regex = @"^WSSEESWWWNW(S|NENNEEEENN(ESSSSW(NWSW|SSEN)|WSWWN(E|WWS(E|SS))))$";
  18. List<int> result = new List<int>();
  19. Stack<string> queue = new Stack<string>();
  20. queue.Push(regex.TrimStart('^').TrimEnd('$'));
  21. while (queue.Count > 0)
  22. {
  23. bool hasParenthesis = false;
  24. int minLength = 0, minIndex = 0;
  25. var str = queue.Pop();
  26. int par = 0, index = 0;
  27. List<int> pipes = new List<int>();
  28. foreach (var c in str)
  29. {
  30. if (c == '(') par++;
  31. if (c == ')')
  32. {
  33. par--;
  34. if (par == 0) break;
  35. }
  36. if (par == 1 && c == '|')
  37. {
  38. pipes.Add(index);
  39. }
  40. if (hasParenthesis == false && par == 1)
  41. {
  42. minIndex = index;
  43. hasParenthesis = true;
  44. }
  45. if (par != 0) minLength++;
  46. index++;
  47. }
  48. if (hasParenthesis == false)
  49. {
  50. (int x, int y) pos = (0, 0);
  51. HashSet<((int x, int y) from, (int x, int y) to)> doors = new HashSet<((int x, int y) from, (int x, int y) to)>();
  52. foreach (var c in str)
  53. {
  54. var bpos = pos;
  55. switch (c)
  56. {
  57. case 'N': pos.y -= 1; break;
  58. case 'S': pos.y += 1; break;
  59. case 'W': pos.x -= 1; break;
  60. case 'E': pos.x += 1; break;
  61. }
  62. doors.Add((bpos, pos));
  63. doors.Add((pos, bpos));
  64. }
  65. result.Add(GetBreadthFirstSearch(doors, pos));
  66. continue;
  67. }
  68. var possibilitiesStr = str.Substring(minIndex + 1, minLength - 1);
  69. List<string> possibilities = new List<string>();
  70. int beforePipe = minIndex;
  71. for (var i = 0; i < pipes.Count; ++i)
  72. {
  73. possibilities.Add(possibilitiesStr.Substring(beforePipe - minIndex, pipes[i] - beforePipe - 1));
  74. beforePipe = pipes[0];
  75. }
  76. possibilities.Add(possibilitiesStr.Substring(beforePipe - minIndex));
  77. foreach (var possibility in possibilities)
  78. {
  79. var nr = str.Substring(0, minIndex) + possibility + str.Substring(minIndex + minLength + 1);
  80. queue.Push(nr);
  81. }
  82. }
  83. Console.WriteLine(result.Max());
  84. }
  85. // https://en.wikipedia.org/wiki/Breadth-first_search
  86. private static int GetBreadthFirstSearch(HashSet<((int x, int y) from, (int x, int y) to)> doors, (int x, int y) togo)
  87. {
  88. var nodesToVisit = new Queue<(int x, int y)>();
  89. var visitedNodes = new HashSet<(int x, int y)>();
  90. var meta = new Dictionary<(int x, int y), (int x, int y)>()
  91. {
  92. { (0, 0), (0, 0) }
  93. };
  94. nodesToVisit.Enqueue((0, 0));
  95. while (nodesToVisit.Count > 0)
  96. {
  97. var node = nodesToVisit.Dequeue();
  98. // Found it!
  99. if (node == togo)
  100. {
  101. var count = GetActionList(togo, meta, node);
  102. return count;
  103. }
  104. foreach ((int mx, int my) mv in new []{ (0, -1), (1, 0), (0, 1), (-1, 0) })
  105. {
  106. (int x, int y) successor = (node.x + mv.mx, node.y + mv.my);
  107. // Continue if no door exist
  108. if (doors.Contains((node, successor)) == false) continue;
  109. if (visitedNodes.Contains(successor)) continue;
  110. if (nodesToVisit.Contains(successor) == false)
  111. {
  112. meta.TryAdd(successor, mv);
  113. nodesToVisit.Enqueue(successor);
  114. }
  115. }
  116. visitedNodes.Add(node);
  117. }
  118. return -1;
  119. }
  120. private static int GetActionList((int x, int y) root, Dictionary<(int x, int y), (int x, int y)> meta, (int x, int y) node)
  121. {
  122. var actionList = new List<(int x, int y)>();
  123. while (meta[node] != (0, 0))
  124. {
  125. var action = meta[node];
  126. node = (node.x - action.x, node.y - action.y);
  127. actionList.Add(action);
  128. }
  129. return actionList.Count;
  130. }
  131. }
  132. }