2019: Day 10 Part 2
This commit is contained in:
parent
f6263f7cd9
commit
22719458d7
1 changed files with 156 additions and 0 deletions
156
2019/day10/part2.rb
Normal file
156
2019/day10/part2.rb
Normal file
|
|
@ -0,0 +1,156 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AsteroidBelt
|
||||||
|
def initialize(text)
|
||||||
|
@grid = parse(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
def asteroids
|
||||||
|
return @asteroids unless @asteroids.nil?
|
||||||
|
|
||||||
|
@asteroids = []
|
||||||
|
@grid.each_with_index do |line, y|
|
||||||
|
line.chars.each_with_index do |cell, x|
|
||||||
|
@asteroids << Asteroid.new(x, y) if cell == '#'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@asteroids
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def parse(text)
|
||||||
|
text.lines
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Asteroid
|
||||||
|
attr_reader :x, :y
|
||||||
|
|
||||||
|
def initialize(x, y)
|
||||||
|
@x = x
|
||||||
|
@y = y
|
||||||
|
end
|
||||||
|
|
||||||
|
def neighbors(asteroids)
|
||||||
|
by_direction = Hash.new { |hash, key| hash[key] = [] }
|
||||||
|
asteroids.each do |asteroid|
|
||||||
|
next if asteroid == self
|
||||||
|
|
||||||
|
theta = direction_to(asteroid).normalize
|
||||||
|
by_direction[theta] << asteroid
|
||||||
|
end
|
||||||
|
by_direction
|
||||||
|
end
|
||||||
|
|
||||||
|
def direction_to(other)
|
||||||
|
dx = other.x - x
|
||||||
|
dy = other.y - y
|
||||||
|
Vector.new(dx, dy)
|
||||||
|
end
|
||||||
|
|
||||||
|
def distance_to(other)
|
||||||
|
dx = other.x - x
|
||||||
|
dy = other.y - y
|
||||||
|
Math.sqrt(dx**2 + dy**2)
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"<Asteroid: #{x},#{y}>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"(#{x},#{y})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Vector
|
||||||
|
attr_reader :x, :y
|
||||||
|
|
||||||
|
def initialize(x, y, normal = false)
|
||||||
|
@x = x
|
||||||
|
@y = y
|
||||||
|
@normal = normal
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize
|
||||||
|
return self if @normal
|
||||||
|
|
||||||
|
div = gcd(@x.abs, @y.abs)
|
||||||
|
Vector.new(Rational(@x / div), Rational(@y / div), true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
s = normalize
|
||||||
|
o = other.normalize
|
||||||
|
|
||||||
|
s.x == o.x && s.y == o.y
|
||||||
|
end
|
||||||
|
|
||||||
|
def eql?(other)
|
||||||
|
self == other
|
||||||
|
end
|
||||||
|
|
||||||
|
def hash
|
||||||
|
n = normalize
|
||||||
|
[n.x, n.y].hash
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"<Vector: #{x},#{y}>"
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"(#{x},#{y})"
|
||||||
|
end
|
||||||
|
|
||||||
|
def from_vertical
|
||||||
|
# (0,1)
|
||||||
|
# 0 /
|
||||||
|
# |t/
|
||||||
|
# |/
|
||||||
|
# (-1,0) 3pi/2 -----+----- +pi/2 (1,0)
|
||||||
|
# |
|
||||||
|
# |
|
||||||
|
# +pi
|
||||||
|
# (0,-1)
|
||||||
|
-Math.atan2(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def gcd(n, m)
|
||||||
|
# Invariant: n >= m
|
||||||
|
n, m = m, n if n < m
|
||||||
|
n, m = m, n % m until m.zero?
|
||||||
|
n
|
||||||
|
end
|
||||||
|
|
||||||
|
input = File.read(File.join(__dir__, 'input'))
|
||||||
|
|
||||||
|
belt = AsteroidBelt.new input
|
||||||
|
|
||||||
|
best = belt.asteroids.max_by do |asteroid|
|
||||||
|
asteroid.neighbors(belt.asteroids).count
|
||||||
|
end
|
||||||
|
pp best
|
||||||
|
|
||||||
|
neighbors = best.neighbors(belt.asteroids)
|
||||||
|
directions = neighbors.keys.sort_by(&:from_vertical)
|
||||||
|
neighbors.values.each do |asteroids|
|
||||||
|
asteroids.sort_by! do |asteroid|
|
||||||
|
best.distance_to(asteroid)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
destroyed = []
|
||||||
|
until neighbors.values.all?(&:empty?)
|
||||||
|
directions.each do |dir|
|
||||||
|
next if neighbors[dir].empty?
|
||||||
|
|
||||||
|
destroyed << neighbors[dir].shift
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
winner = destroyed[199]
|
||||||
|
pp winner
|
||||||
|
puts 100 * winner.x + winner.y
|
||||||
Loading…
Reference in a new issue