Browse Source

D23.2 algo OK! Using searchboxes as suggested on reddit

bastien.monsarrat 6 years ago
parent
commit
845d1a87ff
1 changed files with 97 additions and 79 deletions
  1. 97 79
      D23.2/Program.cs

+ 97 - 79
D23.2/Program.cs

@@ -8,79 +8,94 @@ namespace D23._2
 {
     class Program
     {
-        static int Manhattan((int x, int y, int z) a, (int x, int y, int z) b)
+        public class SearchBox
         {
-            return Math.Abs(a.x - b.x) + Math.Abs(a.y - b.y) + Math.Abs(a.z - b.z);
-        }
-
-        static int InRange(List<(int x, int y, int z, int r)> nanoList, (int x, int y, int z) coord)
-        {
-            int count = 0;
-            foreach (var n in nanoList)
+            // Angle "inférieur gauche"
+            /*
+              
+              Y ^
+                |
+                |
+                |         Z 7
+                |         /
+                |       /
+                |     /
+                |   /
+                | /
+                +______________________> X
+              
+              
+             */
+            (int x, int y, int z) Coord { get; }
+
+            (int x, int y, int z) OpposedCoord => (Coord.x + Size - 1, Coord.y + Size - 1, Coord.z + Size - 1);
+
+            public int Size { get; }
+
+            public int Distance => RangedManhattan((0, 0, 0));
+
+            public SearchBox(int size, (int, int, int) coord)
             {
-                int m = Manhattan(coord, (n.x, n.y, n.z));
-                if (m <= n.r) count++;
+                Size = size;
+                Coord = coord;
             }
-            return count;
-        }
 
-        static HashSet<(int x, int y, int z)> tested = new HashSet<(int x, int y, int z)>();
-        static (int, (int, int, int)) Test(List<(int x, int y, int z, int r)> nanoList, (int x, int y, int z) coord, int i)
-        {
-            var point = coord;
-            var stack = new List<((int x, int y, int z) pos, int count)>();
+            int? bots = null;
+            public int NanoBots
+            {
+                get
+                {
+                    if (bots.HasValue) return bots.Value;
 
-            int maxCount = 0;
-            (int x, int y, int z) bestPosition = coord;
-            int manhattanBest = 0;
+                    int count = 0;
+                    foreach (var (x, y, z, r) in nanoList)
+                    {
+                        int dist = RangedManhattan((x, y, z));
+                        if (dist <= r) count++;
+                    }
+                    bots = count;
 
-            stack.Add((point, 0));
+                    return bots.Value;
+                }
+            }
 
-            while (stack.Count > 0)
+            private int RangedManhattan((int x, int y, int z) coord)
             {
-                stack.Sort((a, b) => b.count.CompareTo(a.count));
+                int manhattan = 0;
 
-                var first = stack.First();
-                point = first.pos;
-                stack.Remove(first);
+                // Si la coordonnée du point est située dans la range Coord -> OpposedCoord,
+                // alors on considère que la distance est de 0 pour la coordonnée en question
+                if (coord.x < Coord.x) manhattan += Coord.x - coord.x;
+                if (coord.x > OpposedCoord.x) manhattan += coord.x - OpposedCoord.x;
 
-                tested.Add(point);
+                if (coord.y < Coord.y) manhattan += Coord.y - coord.y;
+                if (coord.y > OpposedCoord.y) manhattan += coord.y - OpposedCoord.y;
 
-                var count = InRange(nanoList, point);
-                if (count > maxCount)
-                {
-                    maxCount = count;
-                    bestPosition = point;
-                    manhattanBest = Manhattan(point, (0, 0, 0));
-                    stack.RemoveAll(s => s.count < maxCount);
-                    Console.Write($"Best is {maxCount} - Manhattan {manhattanBest}                 \r");
-                }
-                else if (count == maxCount)
-                {
-                    var pmanhattan = Manhattan(point, (0, 0, 0));
-                    if (pmanhattan < manhattanBest)
-                    {
-                        bestPosition = point;
-                        manhattanBest = pmanhattan;
-                        stack.RemoveAll(s => s.count < maxCount);
-                        Console.Write($"Best is {maxCount} - Manhattan {manhattanBest}                 \r");
-                    }
-                }
-                else continue;
+                if (coord.z < Coord.z) manhattan += Coord.z - coord.z;
+                if (coord.z > OpposedCoord.z) manhattan += coord.z - OpposedCoord.z;
 
-                foreach (var (mx, my, mz) in MovementList)
-                {
-                    var mpoint = (point.x + mx * i, point.y + my * i, point.z + mz * i);
-                    if (tested.Contains(mpoint)) continue;
-                    if (stack.Contains((mpoint, count))) continue;
-                    stack.Add((mpoint, count));
-                }
+                return manhattan;
             }
 
-            return (manhattanBest, bestPosition);
+            public SearchBox[] Split()
+            {
+                int size = Size >> 1;
+                return new SearchBox[8]
+                    {
+                        new SearchBox(size, (Coord.x, Coord. y, Coord.z)),
+                        new SearchBox(size, (Coord.x + size, Coord. y, Coord.z)),
+                        new SearchBox(size, (Coord.x, Coord. y, Coord.z + size)),
+                        new SearchBox(size, (Coord.x + size, Coord. y, Coord.z + size)),
+
+                        new SearchBox(size, (Coord.x, Coord. y + size, Coord.z)),
+                        new SearchBox(size, (Coord.x + size, Coord. y + size, Coord.z)),
+                        new SearchBox(size, (Coord.x, Coord. y + size, Coord.z + size)),
+                        new SearchBox(size, (Coord.x + size, Coord. y + size, Coord.z + size)),
+                    };
+            }
         }
 
-        static (int mx, int my, int mz)[] MovementList = new[] { (0, -1, 0), (0, 1, 0), (-1, 0, 0), (1, 0, 0), (0, 0, -1), (0, 0, 1) };
+        static List<(int x, int y, int z, int r)> nanoList = new List<(int x, int y, int z, int r)>();
         static void Main(string[] args)
         {
             if (args.Length < 1) return;
@@ -90,8 +105,6 @@ namespace D23._2
 
             var reg = new Regex(@"pos=<([\d-,]+)>, r=(\d+)");
 
-            var nanoList = new List<(int x, int y, int z, int r)>();
-
             do
             {
                 var line = file.ReadLine();
@@ -107,30 +120,35 @@ namespace D23._2
 
             file.Close();
 
-            int inRange = 0;
-            (int, int, int) best = (0, 0, 0);
-            foreach (var n in nanoList)
-            {
-                int m = InRange(nanoList, (n.x, n.y, n.z));
-                if (m > inRange)
-                {
-                    inRange = m;
-                    best = (n.x, n.y, n.z);
-                }
-            }
+            var sb = Resolve();
 
-            int bestManhattant = 0;
-            for (var i = (int) Math.Pow(2, 16); i >= 1; i /= 2)
+            Console.WriteLine($"Answer is : {sb.Distance}\nNano bots in range : {sb.NanoBots}");
+        }
+
+        private static SearchBox Resolve()
+        {
+            var bsize = (int)Math.Pow(2, 30);
+            var bcoord = -1 * bsize / 2;
+
+            List<SearchBox> SbQueue = new List<SearchBox> { new SearchBox(bsize, (bcoord, bcoord, bcoord)) };
+
+            while (true)
             {
-                Console.Clear();
-                Console.WriteLine($"Testing with i = {i}");
+                SbQueue = SbQueue
+                    .OrderByDescending(s => s.NanoBots)
+                    .ThenBy(s => s.Distance)
+                    .ThenBy(s => s.Size)
+                    .ToList();
 
-                (var manhattan, var nbest) = Test(nanoList, best, i);
-                best = nbest;
-                bestManhattant = manhattan;
-            }
+                var first = SbQueue.First();
+
+                SbQueue.RemoveAt(0);
 
-            Console.WriteLine($"\nAnswer is : {bestManhattant}");
+                if (first.Size == 1)
+                    return first;
+
+                SbQueue.AddRange(first.Split());
+            }
         }
     }
 }