Code for the Advent of Code event
aoc advent-of-code
at rust 95 lines 2.3 kB view raw
1#!/usr/bin/env ruby 2# frozen_string_literal: true 3 4input = $stdin.readline 5 6moves = input.scan(/([RL])(\d+)/).map { |d, a| [d.downcase.to_sym, a.to_i] } 7 8class Point 9 MOVEMENT = { 10 north: ->(steps) { [0, steps] }, 11 east: ->(steps) { [steps, 0] }, 12 south: ->(steps) { [0, -1 * steps] }, 13 west: ->(steps) { [-1 * steps, 0] } 14 }.freeze 15 16 attr_reader :x, :y, :twice 17 18 def initialize 19 @x = 0 20 @y = 0 21 @orientation = 0 22 @visited = [] 23 end 24 25 def orientation 26 MOVEMENT.keys[@orientation] 27 end 28 29 def turn(direction) 30 @orientation += direction == :r ? 1 : MOVEMENT.keys.size - 1 31 @orientation %= MOVEMENT.keys.size 32 end 33 34 def move(steps) 35 dx, dy = MOVEMENT[orientation].call(steps) 36 # puts "#{dx}, #{dy}" 37 current = [@x, @y] 38 target = [@x + dx, @y + dy] 39 40 iterate_horizontal current[0], target[0] if current[1] == target[1] 41 iterate_vertical current[1], target[1] if current[0] == target[0] 42 43 @x, @y = target 44 end 45 46 def iterate_horizontal(current, target) 47 # Exclude our current position from checks 48 current += (current < target ? 1 : -1) 49 # Swap values to make range work if we're walking to the left 50 current, target = target, current if current > target 51 (current..target).each do |x| 52 if @visited.include? [x, @y] 53 @twice ||= [x, @y] 54 else 55 @visited << [x, @y] 56 end 57 end 58 end 59 60 def iterate_vertical(current, target) 61 # Exclude our current position from checks 62 current += (current < target ? 1 : -1) 63 # Swap values to make range work if we're walking down 64 current, target = target, current if current > target 65 (current..target).each do |y| 66 if @visited.include? [@x, y] 67 @twice ||= [@x, y] 68 else 69 @visited << [@x, y] 70 end 71 end 72 end 73 74 def shortest_path 75 @x.abs + @y.abs 76 end 77 78 def real_shortest 79 @twice.map(&:abs).inject(&:+) 80 end 81end 82 83destination = Point.new 84 85moves.each do |move| 86 # puts "Move: #{move[0]} then #{move[1]} steps" 87 destination.turn move[0] 88 destination.move move[1] 89end 90 91puts "Target position: (#{destination.x}, #{destination.y})" 92 93puts "(1) Shortest path is #{destination.shortest_path} steps long" 94 95puts "(2) The REAL shortest path is #{destination.real_shortest} steps long"