77 lines
1.8 KiB
Ruby
77 lines
1.8 KiB
Ruby
require "set"
|
|
|
|
class CrossedWires
|
|
attr_reader :wires
|
|
def initialize(wires)
|
|
@wires = wires
|
|
end
|
|
|
|
def self.for(input)
|
|
new input.split("\n").map { |line| Wire.for line }
|
|
end
|
|
|
|
def intersections
|
|
wires.map(&:positions).map(&:keys).reduce(&:&)
|
|
end
|
|
|
|
def intersection_distances
|
|
intersections
|
|
.map { |intersection| wires.map { |wire| wire.positions[intersection] }.sum }
|
|
end
|
|
|
|
def closest_intersection
|
|
intersections
|
|
.map{ |intersection| intersection.split(",").map(&:to_i) }
|
|
.sort_by { |x, y| x.abs + y.abs }.min
|
|
end
|
|
|
|
class Wire
|
|
attr_reader :turns
|
|
def initialize(turns)
|
|
@turns = turns
|
|
end
|
|
|
|
def self.for(line)
|
|
new line.split(",").map { |turn| Turn.for turn }
|
|
end
|
|
|
|
def positions
|
|
@positions ||= begin
|
|
x = 0
|
|
y = 0
|
|
current_distance = 0
|
|
p = {}
|
|
turns.each do |turn|
|
|
turn.length.times do
|
|
current_distance += 1
|
|
case turn.dir
|
|
when "U"
|
|
y -= 1
|
|
when "D"
|
|
y += 1
|
|
when "L"
|
|
x -= 1
|
|
when "R"
|
|
x += 1
|
|
end
|
|
p["#{x},#{y}"] = current_distance unless p.key?("#{x},#{y}")
|
|
end
|
|
end
|
|
p
|
|
end
|
|
end
|
|
end
|
|
|
|
class Turn
|
|
attr_reader :dir, :length
|
|
def initialize(dir, length)
|
|
@dir = dir
|
|
@length = length
|
|
end
|
|
|
|
def self.for(string)
|
|
new string[0], string[1..].to_i
|
|
end
|
|
end
|
|
end
|