# Advent of Code 2020: Day 12 (Ruby solution)

Piotr Jurewicz
·Dec 12, 2020·

Subscribe to my newsletter and never miss my upcoming articles

Today's puzzle are to simulate ship's routes. The navigation instructions (input file) consists of a sequence of single-character actions paired with integer input values

• Action N means to move north by the given value.
• Action S means to move south by the given value.
• Action E means to move east by the given value.
• Action W means to move west by the given value.
• Action L means to turn left the given number of degrees.
• Action R means to turn right the given number of degrees.
• Action F means to move forward by the given value in the direction the ship is currently facing.

Here is my ship implementation form the first task.

``````require 'matrix'

WORLD_DIRECTIONS = {
'N' => Vector[0, 1],
'E' => Vector[1, 0],
'S' => Vector[0, -1],
'W' => Vector[-1, 0]
}.freeze

def number_of_crosses action, angle
((action == 'L' ? 1 : -1) * angle / 90) % 4
end

class Ship

def initialize
@position = Vector[0, 0]
@rotation = Vector[1, 0]
end

def navigate instructions
instructions.each do |instruction|
action = instruction
value = instruction.scan(/\d+/).first.to_i
process_instruction action, value
end
end

protected

def process_instruction action, value
if action.start_with? 'L', 'R'
rotate action, value
else
move action, value
end
end

def rotate action, angle
number_of_crosses(action, angle).times { @rotation = @rotation.cross }
end

def move action, distance
vector = WORLD_DIRECTIONS.merge('F' => @rotation)[action]
@position += distance * vector
end
end
``````

In the second task, instruction are different:

• Action N means to move the waypoint north by the given value.
• Action S means to move the waypoint south by the given value.
• Action E means to move the waypoint east by the given value.
• Action W means to move the waypoint west by the given value.
• Action L means to rotate the waypoint around the ship left (counter-clockwise) the given number of degrees.
• Action R means to rotate the waypoint around the ship right (clockwise) the given number of degrees.
• Action F means to move forward to the waypoint a number of times equal to the given value.

I provided a second ship implementation extending the previous one. Here is the rest of the code:

``````class ShipWithWaypoints < Ship
def initialize
@waypoint_position = Vector[10, 1]
super
end

protected

def process_instruction action, value
if action.start_with? 'L', 'R'
rotate_waypoint action, value
elsif action.start_with? 'F'
move value
else
move_waypoint action, value
end
end

def rotate_waypoint action, angle
number_of_crosses(action, angle).times { @waypoint_position = @waypoint_position.cross }
end

def move_waypoint action, distance
vector = WORLD_DIRECTIONS[action]
@waypoint_position += distance * vector
end

def move value
@position += @waypoint_position * value
end
end