|
|
@@ -9,98 +9,49 @@ namespace D20._1
|
|
|
{
|
|
|
class Program
|
|
|
{
|
|
|
- public class Group
|
|
|
+ static (int x, int y) MoveTo(char c, (int x, int y) pos)
|
|
|
{
|
|
|
- public int Id { get; set; }
|
|
|
- public int Level { get; set; }
|
|
|
- public string Str { get; set; }
|
|
|
- public List<Group> Groups { get; set; }
|
|
|
- public SortedSet<string> Possibilities { get; set; }
|
|
|
- public Group()
|
|
|
+ switch (c)
|
|
|
{
|
|
|
- Groups = new List<Group>();
|
|
|
- Possibilities = new SortedSet<string>(new PC());
|
|
|
- Str = "";
|
|
|
- Id = 1;
|
|
|
+ case 'N': pos.y -= 1; break;
|
|
|
+ case 'S': pos.y += 1; break;
|
|
|
+ case 'W': pos.x -= 1; break;
|
|
|
+ case 'E': pos.x += 1; break;
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- class PC : IComparer<string>
|
|
|
- {
|
|
|
- public int Compare(string x, string y) => y.Length.CompareTo(x.Length);
|
|
|
+ return pos;
|
|
|
}
|
|
|
|
|
|
- static IEnumerable<string> CombinePossibilities(string Str, List<Group> children, int depth = 0)
|
|
|
+ static Dictionary<(int x, int y), int> makeMap(string input)
|
|
|
{
|
|
|
- if (depth == children.Count) { yield return Str; yield break; }
|
|
|
-
|
|
|
- var child = children[depth];
|
|
|
-
|
|
|
- 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;
|
|
|
- }
|
|
|
- }
|
|
|
+ var result = new Dictionary<(int x, int y), int>();
|
|
|
+ var nodes = new Stack<((int x, int y), int dist)>();
|
|
|
+ ((int x, int y) pos, int dist) cur = ((0, 0), 0);
|
|
|
|
|
|
- static Group BuildGroups(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)
|
|
|
+ foreach (var c in input)
|
|
|
{
|
|
|
- if (priority[index] > level && capture)
|
|
|
- {
|
|
|
- capture = false;
|
|
|
- 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)
|
|
|
+ switch (c)
|
|
|
{
|
|
|
- capture = true;
|
|
|
- group.Str += regex[index];
|
|
|
+ case 'N':
|
|
|
+ case 'S':
|
|
|
+ case 'E':
|
|
|
+ case 'W':
|
|
|
+ cur.pos = MoveTo(c, cur.pos);
|
|
|
+ cur.dist++;
|
|
|
+ result.TryAdd(cur.pos, cur.dist);
|
|
|
+ break;
|
|
|
+ case '(':
|
|
|
+ nodes.Push(cur);
|
|
|
+ break;
|
|
|
+ case '|':
|
|
|
+ cur = nodes.Peek();
|
|
|
+ break;
|
|
|
+ case ')':
|
|
|
+ cur = nodes.Pop();
|
|
|
+ break;
|
|
|
}
|
|
|
-
|
|
|
- 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);
|
|
|
}
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
static void Main(string[] args)
|
|
|
@@ -117,60 +68,12 @@ namespace D20._1
|
|
|
//regex = @"^N(EEENWWW|N)$";
|
|
|
|
|
|
regex = regex.TrimStart('^').TrimEnd('$');
|
|
|
- int par = 0, maxpar = 0;
|
|
|
- var priority = "";
|
|
|
- for (var i = 0; i < regex.Length; ++i)
|
|
|
- {
|
|
|
- if (regex[i] == '(')
|
|
|
- {
|
|
|
- par++;
|
|
|
- if (par > maxpar) maxpar = par;
|
|
|
- }
|
|
|
- if (regex[i] == ')') par--;
|
|
|
- priority += (char)par;
|
|
|
- }
|
|
|
|
|
|
- var root = BuildGroups(0, priority, regex, 0);
|
|
|
+ var map = makeMap(regex);
|
|
|
|
|
|
- var sw = Stopwatch.StartNew();
|
|
|
-
|
|
|
- Test(root);
|
|
|
-
|
|
|
- sw.Stop();
|
|
|
-
|
|
|
- Console.WriteLine(sw.ElapsedMilliseconds);
|
|
|
-
|
|
|
- Dictionary<(int x, int y), int> positions = new Dictionary<(int x, int y), int>();
|
|
|
- positions.Add((0, 0), 0);
|
|
|
-
|
|
|
- foreach (var path in root.Possibilities)
|
|
|
- {
|
|
|
- TestResult(path, positions);
|
|
|
- }
|
|
|
-
|
|
|
- int max = positions.Max(p => p.Value);
|
|
|
- int d = positions.Count(p => p.Value >= 1000);
|
|
|
+ int max = map.Max(p => p.Value);
|
|
|
+ int d = map.Count(p => p.Value >= 1000);
|
|
|
Console.WriteLine($"Ex 1 : {max}\nEx 2 ; {d}");
|
|
|
}
|
|
|
-
|
|
|
- private static void TestResult(string str, Dictionary<(int x, int y), int> positions)
|
|
|
- {
|
|
|
- int dist = 0;
|
|
|
- (int x, int y) pos = (0, 0);
|
|
|
-
|
|
|
- foreach (var c in str)
|
|
|
- {
|
|
|
- switch (c)
|
|
|
- {
|
|
|
- case 'N': pos.y -= 1; break;
|
|
|
- case 'S': pos.y += 1; break;
|
|
|
- case 'W': pos.x -= 1; break;
|
|
|
- case 'E': pos.x += 1; break;
|
|
|
- }
|
|
|
-
|
|
|
- if (positions.TryAdd(pos, dist + 1)) dist = dist + 1;
|
|
|
- else dist = Math.Min(dist + 1, positions[pos]);
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
}
|