2022-10-27 15:42:05 +00:00
|
|
|
namespace AOC2019;
|
|
|
|
|
|
|
|
public sealed class Day10 : Day
|
|
|
|
{
|
|
|
|
private readonly HashSet<(int x, int y)> _asteroids;
|
|
|
|
private (int x, int y) _best = (x: -1, y: -1);
|
|
|
|
private int _bestCanSee;
|
|
|
|
|
2022-10-27 16:36:21 +00:00
|
|
|
public Day10() : base(2019, 10, "Monitoring Station")
|
2022-10-27 15:42:05 +00:00
|
|
|
{
|
|
|
|
_asteroids = Input
|
|
|
|
.Select((r, y) => r.Select((c, x) => (x, y, isAsteroid: c == '#')).ToArray())
|
|
|
|
.SelectMany(r => r)
|
|
|
|
.Where(a => a.isAsteroid)
|
|
|
|
.Select(a => (a.x, a.y))
|
|
|
|
.ToHashSet();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string Part1()
|
|
|
|
{
|
|
|
|
foreach (var asteroid in _asteroids)
|
|
|
|
{
|
|
|
|
var canSee = _asteroids
|
|
|
|
.Except(new[] { asteroid })
|
|
|
|
.Select(a => (x: a.x - asteroid.x, y: a.y - asteroid.y))
|
|
|
|
.GroupBy(a => Math.Atan2(a.y, a.x))
|
|
|
|
.Count();
|
|
|
|
|
|
|
|
if (canSee > _bestCanSee)
|
|
|
|
{
|
|
|
|
_best = asteroid;
|
|
|
|
_bestCanSee = canSee;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $"{_bestCanSee}";
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string Part2()
|
|
|
|
{
|
|
|
|
static IEnumerable<(int x, int y, double angle, double dist)> GetValue(
|
|
|
|
Queue<(int x, int y, double angle, double dist)> q)
|
|
|
|
{
|
|
|
|
if (q.Count > 0) yield return q.Dequeue();
|
|
|
|
}
|
|
|
|
|
|
|
|
return _asteroids
|
|
|
|
.Where(a => a != _best)
|
|
|
|
.Select(a =>
|
|
|
|
{
|
|
|
|
var xDist = a.x - _best.x;
|
|
|
|
var yDist = a.y - _best.y;
|
|
|
|
var angle = Math.Atan2(xDist, yDist);
|
|
|
|
return (a.x, a.y, angle, dist: Math.Sqrt(xDist * xDist + yDist * yDist));
|
|
|
|
})
|
|
|
|
.ToLookup(a => a.angle)
|
|
|
|
.OrderByDescending(a => a.Key)
|
|
|
|
.Select(a => new Queue<(int x, int y, double angle, double dist)>(a.OrderBy(b => b.dist)))
|
|
|
|
.Repeat()
|
|
|
|
.SelectMany(GetValue)
|
|
|
|
.Skip(199)
|
|
|
|
.Take(1)
|
|
|
|
.Select(a => a.x * 100 + a.y)
|
|
|
|
.Single()
|
|
|
|
.ToString();
|
|
|
|
}
|
|
|
|
}
|