Skip to content

Instantly share code, notes, and snippets.

@SleeplessByte
Last active December 12, 2020 11:08
Show Gist options
  • Save SleeplessByte/33e3038244adfb4a6a99b4b3546b43f2 to your computer and use it in GitHub Desktop.
Save SleeplessByte/33e3038244adfb4a6a99b4b3546b43f2 to your computer and use it in GitHub Desktop.
Advent of Code 2020: Day 12 - Rain Risk
require 'benchmark'
class Ship
attr_reader :position
def initialize
self.facing = 90
self.position = Position.new(0, 0)
self.waypoint = Waypoint.new
end
def sail!(instruction)
case instruction.action
when 'N'
position.translate!(0, -instruction.value)
when 'S'
position.translate!(0, instruction.value)
when 'E'
position.translate!( instruction.value, 0)
when 'W'
position.translate!(-instruction.value, 0)
when 'L'
self.facing = (self.facing - instruction.value) % 360
when 'R'
self.facing = (self.facing + instruction.value) % 360
when 'F'
direction = %w[N E S W][facing / 90]
sail! instruction.with_action(direction)
# input only contains 90 180 270 so no need for
# SOS Castoa (gonio).
end
end
def sail_with_waypoint!(instruction)
if %w[N S E W L R].include?(instruction.action)
waypoint.sail! instruction
return
end
dx, dy = waypoint.position.difference(Position.new(0, 0))
self.position.translate!(dx * instruction.value, dy * instruction.value)
end
private
attr_accessor :facing, :waypoint
attr_writer :position
end
class Waypoint
attr_reader :position
def initialize
self.position = Position.new(10, -1)
end
def sail!(instruction)
case instruction.action
when 'N'
position.translate!(0, -instruction.value)
when 'S'
position.translate!(0, instruction.value)
when 'E'
position.translate!( instruction.value, 0)
when 'W'
position.translate!(-instruction.value, 0)
when 'L'
theta = -(instruction.value / 180.to_f * Math::PI)
self.position = Position.new(
(position.x * Math.cos(theta) - position.y * Math.sin(theta)).round,
(position.x * Math.sin(theta) + position.y * Math.cos(theta)).round
)
when 'R'
theta = instruction.value / 180.to_f * Math::PI
self.position = Position.new(
(position.x * Math.cos(theta) - position.y * Math.sin(theta)).round,
(position.x * Math.sin(theta) + position.y * Math.cos(theta)).round
)
end
end
private
attr_accessor :facing
attr_writer :position
end
class Instruction
attr_reader :action, :value
def initialize(action, value)
self.action = action
self.value = value.to_i
end
def with_action(new_action)
Instruction.new(new_action, value)
end
private
attr_writer :action, :value
end
class Position
attr_reader :x, :y
def initialize(x, y)
self.x = x
self.y = y
end
def translate!(x, y)
self.x += x
self.y += y
self
end
def distance(other)
difference(other).map(&:abs).sum
end
def difference(other)
[x - other.x, y - other.y]
end
private
attr_writer :x, :y
end
module NavigationInstructions
def self.from_lines(lines)
lines.map do |line|
line = line.chomp
Instruction.new(line[0], line[1..])
end
end
end
def track(ship)
original = ship.position.dup
yield
original.distance(ship.position)
end
source = 'input.txt'
instructions = NavigationInstructions.from_lines(File.readlines(source))
verbose = false
Benchmark.bmbm do |x|
x.report(:part_1) do
ship = Ship.new
distance = track(ship) do
instructions.each do |instruction|
ship.sail! instruction
puts "[ahoy] #{instruction.action} by #{instruction.value}: #{ship.position.x}, #{ship.position.y}" if verbose
end
end
puts distance
end
x.report(:part_2) do
ship = Ship.new
distance = track(ship) do
instructions.each do |instruction|
ship.sail_with_waypoint! instruction
puts "[ahoy] #{instruction.action} by #{instruction.value}: #{ship.position.x}, #{ship.position.y}" if verbose
end
end
puts distance
end
end
F10
N3
F7
R90
F11
N1
S4
L180
W5
S5
E2
N3
N5
E5
F25
S5
F88
L90
F8
R90
E2
L90
F72
S2
E2
F82
N1
W4
R90
W3
F29
L90
E2
L90
W5
L90
F82
R90
F36
R180
F19
W4
F40
W1
R270
E5
N3
W5
E5
L90
E4
R90
F50
E1
W2
R180
N3
W2
S4
F33
W1
L90
W3
R90
F51
R270
E3
R90
W5
S4
F72
R90
S4
E3
F66
R270
S3
E4
L90
E2
R90
F94
L90
F19
W2
L90
F68
N2
S3
F40
W3
F47
S5
W1
R90
F38
L180
F70
N2
L90
F13
R270
F57
E2
R90
N5
L90
F54
W3
S2
F27
S3
E2
S2
F29
F8
S5
F6
N4
L90
F94
W2
S5
R180
S5
F19
E3
N1
F39
N5
W3
R90
F28
L90
S1
L180
E4
N1
F16
R90
W4
S3
F24
W4
F31
E4
N5
F39
S3
F6
S2
L270
F2
R90
S5
E3
F61
S2
F12
E4
N3
R90
S5
F88
N3
E2
R90
E2
L90
W2
N3
R90
N1
L180
F8
E3
W2
F57
R90
E1
F69
N3
L90
S5
W2
L180
W4
L90
S4
L90
E3
S4
W3
F38
R90
S1
E1
F50
N5
E2
N5
L90
W2
F62
S4
R90
F41
W2
F77
L180
N5
L90
S1
W1
L90
W3
F89
N1
R90
S2
F50
S5
R180
E5
F23
E5
S2
F95
R90
F17
F13
R90
E2
S2
E2
S4
R90
W4
F19
F74
S4
R90
W5
S5
F5
N3
W5
R90
S5
F45
R270
E2
R90
W5
R90
E5
R90
E3
E4
F83
W2
F70
W1
F57
E5
S2
F95
S5
S4
E1
S5
L180
F18
N2
F55
W3
F22
W4
N3
F78
W1
F79
N3
F2
L90
W3
N5
L90
E1
L90
F80
W4
R180
W2
N4
F39
W2
F53
L180
W1
R90
F10
E1
S1
F74
N5
R90
N1
F77
L90
E2
R90
S2
R90
N4
W5
F54
S1
L90
W5
L90
N2
L90
S2
L90
S4
F16
N1
F26
R90
S4
R90
E5
L90
F83
N5
R90
S2
W4
R90
W4
L90
F90
S2
W2
F13
S3
F65
W1
L90
E5
R90
S4
E1
F49
W4
F37
W4
L180
W1
F72
S2
F28
L90
N1
E1
R90
F68
S1
W3
N1
F98
F18
E3
L180
F38
W5
L90
F39
W5
S4
L90
S2
L90
F80
W4
F75
F70
E5
N3
F21
L90
F4
W3
F11
N2
R90
F95
L90
W2
F28
E4
F53
N1
E4
L90
F22
N1
E2
N3
F48
W4
F22
E3
S1
F65
R180
F12
S3
W1
F86
E3
F81
S4
E2
F20
W4
L90
N1
F44
R90
S5
F51
W1
F81
N5
W5
S2
R90
S2
E4
R90
F65
L90
N4
F80
N5
R90
S1
L90
S4
R90
N5
F51
E2
L180
N3
R90
F16
E1
S1
L180
F62
L90
N2
F58
E1
R90
N3
L90
W2
R90
S1
E2
R180
F50
N1
W4
N1
F56
S1
W1
F93
N3
R180
S1
R90
N3
W1
S1
L90
N1
R90
E2
N5
W3
L270
N1
F9
N3
E2
S1
L180
F33
E1
F33
W5
F99
E4
F47
L180
S3
F35
N5
E4
N5
F25
R90
E5
F59
L180
F72
R180
F70
L180
S1
F83
E1
F79
R90
F36
E1
N4
F81
W2
L90
F97
R180
F72
S4
R90
F14
W2
F4
N2
N1
F88
R90
N5
F33
S3
E5
S5
E3
L90
F29
E1
F59
N3
R90
W2
F67
R90
E5
R90
N4
F77
R90
E4
S4
F43
R90
S2
W4
L180
N3
W4
L90
S4
L90
W3
N5
R90
S5
E5
R90
F4
F52
N2
F68
N1
R180
W3
S5
F91
W2
S2
L90
F36
R180
S3
L180
N1
L90
S2
E5
L90
F66
N1
E4
L90
F51
E1
S4
R180
F42
S4
L90
N1
E2
F100
R90
N4
F13
R270
W1
L90
E1
L270
W3
F86
W4
F37
W2
F57
N1
W3
F86
R90
F7
R90
S5
W5
E5
L270
W2
F39
L180
N2
F9
E4
R180
S2
F97
S1
R180
F56
W4
R90
W3
F56
L180
F3
E1
F39
N4
L90
F45
R270
F66
L90
F54
E5
L90
E4
N5
L90
S5
E2
N5
E4
F36
L180
F67
E2
N5
W3
L90
N1
E4
F44
E5
L180
W3
N5
R90
S3
R270
W2
L90
N3
L90
F46
N5
F95
E4
L90
F93
S3
W2
N1
F14
L90
F47
L90
N4
E5
F14
E5
S5
F32
W4
S5
R90
N4
F75
R90
W1
S5
N1
R90
E5
W1
F82
R180
N4
E2
S5
E4
S3
F60
L90
W2
F61
E2
L180
N2
F9
W2
L90
F20
W1
F59
S5
L180
F9
S2
S3
L90
E1
N2
W2
L90
W1
S5
F56
S4
F10
W2
N3
N5
F41
S4
L90
W2
S1
R90
F47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment