예제 #1
0
        public static void P2()
        {
            var s = Utilities.GetLinesFromFile("Day10.txt").Select(x => x.Replace(",", "").ToArray()).ToArray();

            var arr = new char[s.GetLength(0), s.GetLength(0)];

            for (int i = 0; i < s.GetLength(0); i++)
            {
                for (int j = 0; j < s[0].GetLength(0); j++)
                {
                    arr[i, j] = s[i][j];
                }
            }
            int[] centerpoint = new int[] { 20, 23 };

            arr[centerpoint[0], centerpoint[1]] = '*';

            var angles = new Dictionary <float, List <Asteroid> >();

            for (int i = 0; i < s.GetLength(0); i++)
            {
                for (int j = 0; j < s[0].GetLength(0); j++)
                {
                    if (arr[i, j] == '#')
                    {
                        var angle = (float)(Math.Atan2((centerpoint[0] - i), (centerpoint[1] - j)) * (180 / (Math.PI)));

                        var x1 = (angle < 0 ? 360 : 0);
                        angle = angle + (angle < 0 ? 360 : 0);
                        angle = angle + (angle < 90 ? 360 : 0);


                        //Console.WriteLine($"x{j} y{i} angle: {angle}");
                        if (!angles.ContainsKey(angle))
                        {
                            angles[angle] = new List <Asteroid>();
                        }

                        angles[angle].Add(new Asteroid()
                        {
                            coords = $"x{j} y{i}", dist = Distance(centerpoint, new int[] { j, i }), x = j, y = i
                        });
                    }
                }
            }
            var      targets   = angles.OrderBy(a => a.Key).ToList();
            Asteroid lasthit   = new Asteroid();
            int      countdown = 200;
            int      it        = 0;

            while (countdown > 0)
            {
                if (targets[it].Value.Count > 0)
                {
                    var tdist = targets[it].Value.Min(x => x.dist);
                    var t     = targets[it].Value.First(v => v.dist == tdist);
                    lasthit = t;
                    Console.WriteLine($"PEW! {t.coords}");
                    targets[it].Value.Remove(t);
                    countdown--;
                }
                it++;

                if (it >= targets.Count())
                {
                    it = 0;
                }
            }
            Console.WriteLine($"Last ateroid hit: {lasthit.coords} answer is: {lasthit.answer}");
        }
예제 #2
0
파일: Day10.cs 프로젝트: hervala/AoC2019
        public static int Vaporize200Asteroids(string[] asteroidMap)
        {
            if (asteroidMap is null || asteroidMap.Length == 0)
            {
                throw new ArgumentException("map null or empty", nameof(asteroidMap));
            }

            var asteroids = new Dictionary <Point, Asteroid>();
            var mapXMax   = asteroidMap[0].Length - 1;
            var mapYMax   = asteroidMap.Length - 1;

            for (int y1 = 0; y1 <= mapYMax; y1++)
            {
                for (int x1 = 0; x1 <= mapXMax; x1++)
                {
                    if (asteroidMap[y1].Substring(x1, 1) == "#")
                    {
                        var asteroid = new Asteroid(x1, y1);
                        asteroids.Add(asteroid.Location, asteroid);
                        for (int y2 = 0; y2 <= mapYMax; y2++)
                        {
                            for (int x2 = 0; x2 <= mapXMax; x2++)
                            {
                                if (asteroidMap[y2].Substring(x2, 1) == "#" && !(x2 == x1 && y2 == y1))
                                {
                                    var angle = (int)(((Math.Atan2((double)y2 - y1, (double)x2 - x1) * (180 / Math.PI) + 360) % 360) * 100); // multiplied by 100 so the precision is greater and I can still use array with int index
                                    asteroid.AsteroidInView[angle] = true;
                                    if (!(asteroid.AsteroidsInView.TryGetValue(angle, out var asteroidsInLine)))
                                    {
                                        asteroidsInLine = new List <Asteroid>();
                                        asteroid.AsteroidsInView.Add(angle, asteroidsInLine);
                                    }
                                    asteroidsInLine.Add(new Asteroid(x2, y2, x1, y1));
                                }
                            }
                        }
                    }
                }
            }

            var      maxAsteroidsInView = int.MinValue;
            Asteroid bestAsteroid       = null;

            foreach (var asteroid in asteroids)
            {
                var asteroidsSeen = asteroid.Value.AsteroidInView.Count(value => value);
                if (asteroidsSeen > maxAsteroidsInView)
                {
                    maxAsteroidsInView = asteroidsSeen;
                    bestAsteroid       = asteroid.Value;
                }
            }

            Asteroid target = null;

            if (bestAsteroid != null)
            {
                var asteroidsVaporized = 0;
                var angle = 36000 - (90 * 100);  // zero is at X acsel. Se rewind 90 degrees (times 100 because the index)
                while (asteroidsVaporized < 200)
                {
                    if (bestAsteroid.AsteroidsInView.TryGetValue(angle, out var asteroidsInSight))
                    {
                        var minDistance = asteroidsInSight.Min(a => a.Vaporized ? double.MaxValue : a.Distance);
                        target = asteroidsInSight.Find(a => a.Distance == minDistance);
                        target.Vaporize();
                        asteroidsVaporized += 1;
                    }
                    angle += 1;
                    if (angle % 36000 == 0)
                    {
                        angle = 0;
                    }
                }
            }


            return(target == null ? throw new Exception("something went wrong") : target.X * 100 + target.Y);
        }
예제 #3
0
 private static double Angle(Asteroid baseAsteroid, Asteroid asteroid)
 {
     return(Math.Atan2(asteroid.Y - baseAsteroid.Y, asteroid.X - baseAsteroid.X));
 }
예제 #4
0
        public AsteroidMap VisibilityMap(int stationRow, int stationCol)
        {
            // Create a map of what other asteroids are visible if i put a station on the inputted asteroid.
            Asteroid    station = new Asteroid(stationRow, stationCol, null);
            AsteroidMap map     = new AsteroidMap((string[])this.rows.Clone(), station);

            station.map = map;

            // If there is no asteroid in the inputted area, return null;
            if (map.GetCell(stationRow, stationCol) != ASTEROID)
            {
                Console.WriteLine("ERROR! You asked for a visibility map for a location that has no asteroid.");
                return(null);
            }

            // Logic:
            // Look directly to the left of me, find the first asteroid, and consider everything else blocked.
            // Look directly to the right of me, find the first asteroid, and consider everything else blocked.
            // Look at the entire row above me.  Find asteroids, and block everything behind it.
            // And then move up a row.
            // Look at the entire row below me.  Find any asteroids, and block everything behind it.


            for (int columnId = (stationCol - 1); columnId >= 0; columnId--)
            {
                int rowId = stationRow;
                if (map.GetCell(rowId, columnId) == ASTEROID)
                {
                    map.SetCellVisible(rowId, columnId, stationRow, stationCol);
                    // break;
                }
            }

            for (int columnId = (stationCol + 1); columnId < this.mapWidth; columnId++)
            {
                int rowId = stationRow;
                if (map.GetCell(rowId, columnId) == ASTEROID)
                {
                    map.SetCellVisible(rowId, columnId, stationRow, stationCol);
                    //break;
                }
            }

            for (int rowId = (stationRow - 1); rowId >= 0; rowId--)
            {
                for (int colId = 0; colId < this.mapWidth; colId++)
                {
                    if (map.GetCell(rowId, colId) == ASTEROID)
                    {
                        map.SetCellVisible(rowId, colId, stationRow, stationCol);
                        //break;
                    }
                }
            }

            for (int rowId = (stationRow + 1); rowId < this.mapHeight; rowId++)
            {
                for (int colId = 0; colId < this.mapWidth; colId++)
                {
                    if (map.GetCell(rowId, colId) == ASTEROID)
                    {
                        map.SetCellVisible(rowId, colId, stationRow, stationCol);
                        //break;
                    }
                }
            }

            return(map);
        }
예제 #5
0
 public int GetDistanceTo(Asteroid asteroid)
 {
     return(Math.Abs(asteroid.X - this.X) + Math.Abs(asteroid.Y - this.Y));
 }