bastien.monsarrat 6 years ago
parent
commit
963d332c1a
4 changed files with 177 additions and 0 deletions
  1. 6 0
      Adv2018.sln
  2. 10 0
      D22.2/D22.2.csproj
  3. 153 0
      D22.2/Program.cs
  4. 8 0
      D22.2/Properties/launchSettings.json

+ 6 - 0
Adv2018.sln

@@ -89,6 +89,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D21.1and2", "D21.1\D21.1and
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D22.1", "D22.1\D22.1.csproj", "{E3050FCD-AA84-418E-9257-24E0C174AE82}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D22.2", "D22.2\D22.2.csproj", "{1B878AC4-1487-4FC0-87BB-89D69C9A8428}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -267,6 +269,10 @@ Global
 		{E3050FCD-AA84-418E-9257-24E0C174AE82}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{E3050FCD-AA84-418E-9257-24E0C174AE82}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E3050FCD-AA84-418E-9257-24E0C174AE82}.Release|Any CPU.Build.0 = Release|Any CPU
+		{1B878AC4-1487-4FC0-87BB-89D69C9A8428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{1B878AC4-1487-4FC0-87BB-89D69C9A8428}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{1B878AC4-1487-4FC0-87BB-89D69C9A8428}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{1B878AC4-1487-4FC0-87BB-89D69C9A8428}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 10 - 0
D22.2/D22.2.csproj

@@ -0,0 +1,10 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <RootNamespace>D22._2</RootNamespace>
+    <LangVersion>7.3</LangVersion>
+  </PropertyGroup>
+
+</Project>

+ 153 - 0
D22.2/Program.cs

@@ -0,0 +1,153 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+
+namespace D22._2
+{
+    class Program
+    {
+        enum EnumTool
+        {
+            Neither,
+            Torch,
+            Climbing
+        }
+
+        enum EnumTerrain
+        {
+            Rocky  = 0,
+            Wet    = 1,
+            Narrow = 2
+        }
+
+        static readonly Dictionary<EnumTerrain, EnumTool[]> AuthTool = new Dictionary<EnumTerrain, EnumTool[]>
+        {
+            { EnumTerrain.Rocky, new [] { EnumTool.Torch, EnumTool.Climbing } },
+            { EnumTerrain.Wet, new [] { EnumTool.Climbing, EnumTool.Neither } },
+            { EnumTerrain.Narrow, new [] { EnumTool.Torch, EnumTool.Neither } },
+        };
+
+        static (int mx, int my)[] MoveSequence = new[] { (0, -1), (-1, 0), (1, 0), (0, 1) };
+
+        static int Manhattan((int x, int y) a, (int x, int y) b)
+        {
+            return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y);
+        }
+
+        static int UniformCostSearch((int x, int y) start, (int x, int y) goal, int depth)
+        {
+            var node = start;
+            EnumTool tool = EnumTool.Torch;
+            int cost = 0;
+            var frontier = new List<((int x, int y) node, int cost, EnumTool tool)>();
+            var explored = new HashSet<((int x, int y), EnumTool tool)>();
+
+            frontier.Add((node, cost, tool));
+
+            while (frontier.Count > 0)
+            {
+                frontier.Sort((a, b) => a.cost.CompareTo(b.cost));
+
+                var q = frontier.First();
+                frontier.RemoveAt(0);
+
+                cost = q.cost;
+                node = q.node;
+                tool = q.tool;
+
+                var terrain = graph[node];
+
+                if (node == goal && tool == EnumTool.Torch) return cost;
+
+                explored.Add((node, tool));
+
+                foreach (var ntool in AuthTool[terrain])
+                {
+                    if (ntool == tool) continue;
+                    if (explored.Contains((node, ntool)) == true) continue;
+
+                    frontier.Add((node, cost + 7, ntool));
+                }
+
+                foreach (var (mx, my) in MoveSequence)
+                {
+                    (int x, int y) n = (node.x + mx, node.y + my);
+                    if (n.x < 0 || n.y < 0 || n.x > goal.x + 15 || n.y > goal.y + 50) continue;
+
+                    if (explored.Contains((n, tool)) == true) continue;
+
+                    if (graph.ContainsKey(n) == false)
+                        ExtendMap(depth, goal, n);
+
+                    var nterrain = graph[n];
+                    if (AuthTool[nterrain].Contains(tool) == false) continue;
+
+                    if (frontier.Contains((n, cost + 1, tool)) == false)
+                    {
+                        frontier.RemoveAll(f => f.node == n && f.cost > cost + 1);
+                        frontier.Add((n, cost + 1, tool));
+                    }
+                }
+            }
+
+            return -1;
+        }
+
+        static Dictionary<(int, int), int> erosionLevels = new Dictionary<(int, int), int>();
+        static Dictionary<(int, int), EnumTerrain> graph = new Dictionary<(int, int), EnumTerrain>();
+
+        static void Main(string[] args)
+        {
+            if (args.Length < 1) return;
+            if (File.Exists(args[0]) == false) return;
+
+            var file = File.OpenText(args[0]);
+
+            int depth = int.Parse(file.ReadLine().Substring("depth: ".Length));
+            int[] arrayCoord = file.ReadLine().Substring("target: ".Length).Split(",").Select(s => int.Parse(s)).ToArray();
+            (int x, int y) coord = (arrayCoord[0], arrayCoord[1]);
+            file.Close();
+
+            ExtendMap(depth, (0, 0), (0, 0));
+
+            var sw = Stopwatch.StartNew();
+
+            var cost = UniformCostSearch((0, 0), coord, depth);
+
+            sw.Stop();
+
+            Console.WriteLine(sw.ElapsedMilliseconds);
+
+            Console.WriteLine($"Shortest path costs {cost} minutes");
+        }
+
+        private static void ExtendMap(int depth, (int x, int y) coord, (int x, int y) extension)
+        {
+            ComputeRisk(coord, extension, depth);
+        }
+
+        private static void ComputeRisk((int x, int y) coord, (int x, int y) pos, int depth)
+        {
+            int geo = 0;
+            if (pos != (0, 0) && pos != coord)
+            {
+                if (pos.x == 0) geo = pos.y * 48271;
+                else if (pos.y == 0) geo = pos.x * 16807;
+                else
+                {
+                    if (erosionLevels.ContainsKey((pos.x - 1, pos.y)) == false) ComputeRisk(coord, (pos.x - 1, pos.y), depth);
+                    if (erosionLevels.ContainsKey((pos.x, pos.y - 1)) == false) ComputeRisk(coord, (pos.x, pos.y - 1), depth);
+                    geo = erosionLevels[(pos.x - 1, pos.y)] * erosionLevels[(pos.x, pos.y - 1)];
+                }
+            }
+
+            int ero = (geo + depth) % 20183;
+            EnumTerrain type = (EnumTerrain) (ero % 3);
+
+            erosionLevels.Add(pos, ero);
+            graph.Add(pos, type);
+        }
+    }
+}

+ 8 - 0
D22.2/Properties/launchSettings.json

@@ -0,0 +1,8 @@
+{
+  "profiles": {
+    "D22.2": {
+      "commandName": "Project",
+      "commandLineArgs": "\"..\\..\\..\\..\\D22.1\\input.txt\" "
+    }
+  }
+}