2019: Day 11 Part 2
This commit is contained in:
parent
a2208a8f5f
commit
2f0130cda7
2 changed files with 173 additions and 0 deletions
|
|
@ -137,6 +137,7 @@ module Intcode
|
|||
nil
|
||||
when 9
|
||||
move_relative_base!
|
||||
nil
|
||||
when 99
|
||||
:done_executing
|
||||
else
|
||||
|
|
|
|||
172
2019/day11/part2.rb
Normal file
172
2019/day11/part2.rb
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'set'
|
||||
require_relative 'intcode'
|
||||
|
||||
Point = Struct.new(:x, :y) do
|
||||
def to_s
|
||||
"(#{x}, #{y})"
|
||||
end
|
||||
end
|
||||
|
||||
class Hull
|
||||
def initialize
|
||||
@panels = Hash.new { |hash, key| hash[key] = :black }
|
||||
@painted = Set.new
|
||||
end
|
||||
|
||||
def color_at(point)
|
||||
@panels[point]
|
||||
end
|
||||
|
||||
def paint(point, color)
|
||||
@painted << point
|
||||
@panels[point] = color
|
||||
end
|
||||
|
||||
def painted
|
||||
@painted.count
|
||||
end
|
||||
|
||||
def corners
|
||||
min_x = +Float::INFINITY
|
||||
min_y = +Float::INFINITY
|
||||
max_x = -Float::INFINITY
|
||||
max_y = -Float::INFINITY
|
||||
|
||||
@panels.keys.each do |p|
|
||||
min_x = [min_x, p.x].min
|
||||
min_y = [min_y, p.y].min
|
||||
max_x = [max_x, p.x].max
|
||||
max_y = [max_y, p.y].max
|
||||
end
|
||||
|
||||
upper_left = Point.new(min_x, min_y)
|
||||
lower_right = Point.new(max_x, max_y)
|
||||
[upper_left, lower_right]
|
||||
end
|
||||
|
||||
def to_s
|
||||
tl, br = corners
|
||||
|
||||
s = String.new
|
||||
(tl.y..br.y).each do |y|
|
||||
(tl.x..br.x).each do |x|
|
||||
s << char(color_at(Point.new(x, y)))
|
||||
end
|
||||
s << "\n"
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
def char(code)
|
||||
case code
|
||||
when :black
|
||||
' '
|
||||
when :white
|
||||
# Unicode full block
|
||||
"\u2588"
|
||||
else
|
||||
raise ArgumentError, "unexpected color code: #{code}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class DoneExecuting < StandardError; end
|
||||
|
||||
class Robot
|
||||
def initialize(program, hull)
|
||||
@computer = Intcode::Computer.new(program.as_memory) { on_input }
|
||||
@hull = hull
|
||||
@facing = :up
|
||||
@position = Point.new(0, 0)
|
||||
end
|
||||
|
||||
def step
|
||||
color_output = nil
|
||||
direction_output = nil
|
||||
|
||||
color_output = tick until color_output
|
||||
direction_output = tick until direction_output
|
||||
|
||||
@hull.paint(@position, color(color_output))
|
||||
@facing = turn(@facing, direction_output)
|
||||
@position = move(@position, @facing)
|
||||
end
|
||||
|
||||
def tick
|
||||
ret = @computer.tick
|
||||
raise DoneExecuting if ret == :done_executing
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
def on_input
|
||||
color = @hull.color_at(@position)
|
||||
case color
|
||||
when :black
|
||||
0
|
||||
when :white
|
||||
1
|
||||
else
|
||||
raise ArgumentError, "unexpected color: #{color}"
|
||||
end
|
||||
end
|
||||
|
||||
def color(code)
|
||||
case code
|
||||
when 0
|
||||
:black
|
||||
when 1
|
||||
:white
|
||||
else
|
||||
raise ArgumentError, "unexpected color code: #{code}"
|
||||
end
|
||||
end
|
||||
|
||||
DIRECTIONS = %i[up right down left].freeze
|
||||
|
||||
def turn(facing, direction_code)
|
||||
idx = DIRECTIONS.index(facing)
|
||||
case direction_code
|
||||
when 0
|
||||
# left 90 degrees (ccw)
|
||||
next_idx = (idx - 1) % DIRECTIONS.length
|
||||
when 1
|
||||
# right 90 degrees (cw)
|
||||
next_idx = (idx + 1) % DIRECTIONS.length
|
||||
else
|
||||
raise ArgumentError, "unexpected direction code: #{direction_code}"
|
||||
end
|
||||
DIRECTIONS.fetch(next_idx)
|
||||
end
|
||||
|
||||
def move(pos, direction)
|
||||
case direction
|
||||
when :up
|
||||
Point.new(pos.x, pos.y - 1)
|
||||
when :down
|
||||
Point.new(pos.x, pos.y + 1)
|
||||
when :left
|
||||
Point.new(pos.x - 1, pos.y)
|
||||
when :right
|
||||
Point.new(pos.x + 1, pos.y)
|
||||
else
|
||||
raise ArgumentError, "unexpected direction: #{direction}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hull = Hull.new
|
||||
hull.paint(Point.new(0, 0), :white)
|
||||
|
||||
program = Intcode.read(File.join(__dir__, 'input'))
|
||||
robot = Robot.new(program, hull)
|
||||
|
||||
loop do
|
||||
robot.step
|
||||
rescue DoneExecuting
|
||||
break
|
||||
end
|
||||
|
||||
puts hull
|
||||
Loading…
Reference in a new issue