Example #1
0
 public static void insertIntoDictionary(SortedList <double, SortedList <int, Asteroid> > d, double slope, Asteroid a, int sort)
 {
     if (d.ContainsKey(slope))
     {
         d[slope].Add(sort, a);
     }
     else
     {
         SortedList <int, Asteroid> list = new SortedList <int, Asteroid>();
         list.Add(sort, a);
         d.Add(slope, list);
     }
 }
Example #2
0
        static void Main(string[] args)
        {
            string input = @"....#...####.#.#...........#........
#####..#.#.#......#####...#.#...#...
##.##..#.#.#.....#.....##.#.#..#....
...#..#...#.##........#..#.......#.#
#...##...###...###..#...#.....#.....
##.......#.....#.........#.#....#.#.
..#...#.##.##.....#....##..#......#.
..###..##..#..#...#......##...#....#
##..##.....#...#.#...#......#.#.#..#
...###....#..#.#......#...#.......#.
#....#...##.......#..#.......#..#...
#...........#.....#.....#.#...#.##.#
###..#....####..#.###...#....#..#...
##....#.#..#.#......##.......#....#.
..#.#....#.#.#..#...#.##.##..#......
...#.....#......#.#.#.##.....#..###.
..#.#.###.......#..#.#....##.....#..
.#.#.#...#..#.#..##.#..........#...#
.....#.#.#...#..#..#...###.#...#.#..
#..#..#.....#.##..##...##.#.....#...
....##....#.##...#..........#.##....
...#....###.#...##........##.##..##.
#..#....#......#......###...........
##...#..#.##.##..##....#..#..##..#.#
.#....#..##.....#.#............##...
.###.........#....#.##.#..#.#..#.#..
#...#..#...#.#.#.....#....#......###
#...........##.#....#.##......#.#..#
....#...#..#...#.####...#.#..#.##...
......####.....#..#....#....#....#.#
.##.#..###..####...#.......#.#....#.
#.###....#....#..........#.....###.#
...#......#....##...##..#..#...###..
..#...###.###.........#.#..#.#..#...
.#.#.............#.#....#...........
..#...#.###...##....##.#.#.#....#.#.";

            string[] lines = input.Split('\n');
            char[,] map = new char[lines.Length, lines.Length];
            for (int y = 0; y < lines.Length; y++)
            {
                string line = lines[y].Trim();
                for (int x = 0; x < line.Length; x++)
                {
                    map[x, y] = line[x];
                }
            }
            int maxDetected = 0;
            int bestBaseX   = 0;
            int bestBaseY   = 0;

            // loop over grid and check each asteroid
            for (int baseY = 0; baseY < lines.Length; baseY++)
            {
                for (int baseX = 0; baseX < lines.Length; baseX++)
                {
                    if (map[baseX, baseY] == '.')
                    {
                        continue;
                    }                                                                           // only check asteroids
                    Dictionary <double, bool> slopesBiggerX  = new Dictionary <double, bool>(); // the number of unique slopes is the number of asteroids we can see
                    Dictionary <double, bool> slopesSmallerX = new Dictionary <double, bool>();
                    bool sawUndefinedUp   = false;
                    bool sawUndefinedDown = false;
                    for (int otherY = 0; otherY < lines.Length; otherY++)
                    {
                        for (int otherX = 0; otherX < lines.Length; otherX++)
                        {
                            if (map[otherX, otherY] == '.')
                            {
                                continue;
                            }                                         // only check asteroids
                            if (baseX == otherX)
                            {
                                if (baseY == otherY)
                                {
                                    continue;
                                }                                  // same place
                                else
                                {
                                    // undefined slope;
                                    if (otherY < baseY)
                                    {
                                        sawUndefinedUp = true;
                                    }
                                    else
                                    {
                                        sawUndefinedDown = true;
                                    }
                                }
                            }
                            else
                            {
                                double slope = calcSlope(baseX, otherX, baseY, otherY);
                                if (otherX > baseX)
                                {
                                    slopesBiggerX[slope] = true;
                                }
                                else
                                {
                                    slopesSmallerX[slope] = true;
                                }
                            }
                        }
                    }
                    int seen = slopesBiggerX.Count + slopesSmallerX.Count + (sawUndefinedDown?1:0) + (sawUndefinedUp?1:0);
                    if (seen > maxDetected)
                    {
                        maxDetected = seen;
                        bestBaseX   = baseX;
                        bestBaseY   = baseY;
                    }
                }
            }
            Console.WriteLine("Part 1: " + maxDetected);

            //------Part 2-------------
            SortedList <int, Asteroid> undefinedUp   = new SortedList <int, Asteroid>();                                        // asteroids directly above me sorted from closest to furthest
            SortedList <int, Asteroid> undefinedDown = new SortedList <int, Asteroid>();                                        // asteroids directly below me sorted from closest to furthest
            SortedList <double, SortedList <int, Asteroid> > biggerX  = new SortedList <double, SortedList <int, Asteroid> >(); // asteroids on my right side sorted by slope to me ascending, then closest first
            SortedList <double, SortedList <int, Asteroid> > smallerX = new SortedList <double, SortedList <int, Asteroid> >(); // asteroids on my left side sorted by slope to me descending, then closest first

            for (int y = 0; y < lines.Length; y++)
            {
                for (int x = 0; x < lines.Length; x++)
                {
                    if (map[x, y] == '.')
                    {
                        continue;
                    }                               // only check asteroids
                    if (bestBaseX == x)
                    {
                        if (bestBaseY == y)
                        {
                            continue;
                        }                                 // same place as me
                        else
                        {
                            // undefined slope;
                            if (y < bestBaseY)
                            {
                                undefinedUp.Add(-y, new Asteroid(x, y, 0));
                            }                                                            // use -y as key for descending sort on y
                            else
                            {
                                undefinedDown.Add(y, new Asteroid(x, y, 0));
                            }
                        }
                    }
                    else
                    {
                        double slope = calcSlope(bestBaseX, x, bestBaseY, y);
                        if (x > bestBaseX)
                        {
                            insertIntoDictionary(biggerX, slope, new Asteroid(x, y, slope), x);
                        }
                        else
                        {
                            insertIntoDictionary(smallerX, slope, new Asteroid(x, y, slope), -x);
                        }                                                                            // sort on -x for a descending sort
                    }
                }
            }
            int      counter = 0;
            Asteroid last    = null;

            while (counter < 200)
            {
                // starting from up rotate clockwise shooting 1 asteroid at each position
                if (undefinedUp.Count > 0)
                {
                    last = undefinedUp.Values[0];
                    undefinedUp.RemoveAt(0);
                    counter++;
                    if (counter == 200)
                    {
                        break;
                    }
                }
                foreach (KeyValuePair <double, SortedList <int, Asteroid> > kvp in biggerX)
                {
                    SortedList <int, Asteroid> val = kvp.Value;
                    if (val.Count > 0)
                    {
                        last = val.Values[0];
                        val.RemoveAt(0);
                        counter++;
                        if (counter == 200)
                        {
                            break;
                        }
                    }
                }
                if (undefinedDown.Count > 0)
                {
                    last = undefinedDown.Values[0];
                    undefinedDown.RemoveAt(0);
                    counter++;
                    if (counter == 200)
                    {
                        break;
                    }
                }
                foreach (KeyValuePair <double, SortedList <int, Asteroid> > kvp in smallerX)
                {
                    SortedList <int, Asteroid> val = kvp.Value;
                    if (val.Count > 0)
                    {
                        last = val.Values[0];
                        val.RemoveAt(0);
                        counter++;
                        if (counter == 200)
                        {
                            break;
                        }
                    }
                }
            }
            Console.WriteLine("Part 2: (" + last.x + "," + last.y + ")");
        }
Example #3
0
        private static void Part2(Point station)
        {
            var sw = System.Diagnostics.Stopwatch.StartNew();

            var input = File.ReadAllLines("input.txt");

            var map = new HashSet <Point>();
            int y   = 0;

            foreach (string line in input)
            {
                int x = 0;
                foreach (char c in line)
                {
                    if (c == '#')
                    {
                        map.Add(new Point(x, y));
                    }
                    x++;
                }
                y++;
            }

            map.Remove(station);
            var polarMap = new HashSet <Asteroid>();
            var angles   = new SortedList <double, int>();
            int idx      = 0;

            foreach (Point p in map)
            {
                double angle    = GeometryUtil.GetAngle(station, p);
                var    asteroid = new Asteroid(GeometryUtil.GetPolarCoordinate(station, p), p);
                polarMap.Add(asteroid);
                if (!angles.ContainsKey(angle))
                {
                    angles.Add(angle, idx);
                    idx++;
                }
            }

            int numDestroyed = 0;
            int curAngle     = angles.IndexOfKey(-Math.PI / 2);

            while (polarMap.Any())
            {
                Asteroid toRemove = polarMap.Where(p => Math.Abs(p.Polar.Theta - angles.Keys[curAngle]) < double.Epsilon).OrderBy(p => p.Polar.R).FirstOrDefault();
                if (polarMap.Remove(toRemove))
                {
                    numDestroyed++;
                    if (numDestroyed == 200)
                    {
                        Console.WriteLine($"Part 2: {toRemove.Rectangular}, {toRemove.Rectangular.X * 100 + toRemove.Rectangular.Y}");
                    }
                }

                curAngle++;
                if (curAngle >= angles.Count)
                {
                    curAngle = 0;
                }
            }

            sw.Stop();
            System.Diagnostics.Debug.WriteLine(sw.Elapsed);
        }
Example #4
0
 public void IdentifyMonitoringStation()
 {
     HighestNumberOfVisibleAsteroids = _asteroids.Select(x => x.NumberOfVisibleAsteroids).Max();
     MonitoringStationLocation       = _asteroids.Single(x => x.NumberOfVisibleAsteroids == HighestNumberOfVisibleAsteroids);
 }
Example #5
0
 public static double CalculateRadiansBetweenAsteroids(Asteroid a, Asteroid b)
 {
     return(Math.Atan2(-1 * (b.Y - a.Y), b.X - a.X));
 }
Example #6
0
        public static List <Asteroid> DestroyAsteroidsInOrder(Dictionary <Point, Asteroid> asteroids, Asteroid firingLocation)
        {
            var angles = asteroids.Values.Except(new[] { firingLocation }).Select <Asteroid, (Asteroid Asteroid, double Angle)>(_ => (_, firingLocation.GetAngleTo(_))).OrderBy(_ => _.Angle).GroupBy(_ => _.Angle);
            Dictionary <double, List <Asteroid> > firingSequence = new Dictionary <double, List <Asteroid> >();

            foreach (var a in angles)
            {
                firingSequence.Add(a.Key, a.Select(_ => _.Asteroid).OrderBy(_ => _.DistanceTo(firingLocation)).ToList());
            }
            List <Asteroid> destroyedAsteroids = new List <Asteroid>();
            bool            shotFired;

            do
            {
                shotFired = false;
                foreach (var item in firingSequence)
                {
                    if (item.Value.Any())
                    {
                        Console.WriteLine($"{item.Key}");
                        var target = item.Value.First();
                        item.Value.Remove(target);
                        destroyedAsteroids.Add(target);
                        shotFired = true;
                    }
                }
            } while (shotFired);
            return(destroyedAsteroids);
        }