class DirectionString attr_reader :string, :start_position def initialize(string, start_position=[1, 1]) @string = string @start_position = start_position end def final_position return start_position if string.empty? self.class.new(string[1..], next_position).final_position end def next_position case string[0] when "D" [start_position[0], start_position[1] + 1] when "U" [start_position[0], start_position[1] - 1] when "L" [start_position[0] - 1, start_position[1]] when "R" [start_position[0] + 1, start_position[1]] end.map{ |pos| pos.clamp(0, 2) } end end def reduce(array, initial_value) acc = initial_value array.each do |value| acc = yield(acc, value) end acc end input = STDIN.read.chomp direction_strings = input.split KEYPAD = [[ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]] def keypad_digit(position) x, y = position KEYPAD[y][x] end digits = [] direction_strings.inject([1, 1]) do |acc, x| y = DirectionString.new(x, acc).final_position digits << keypad_digit(y) y end puts "Part 1: #{digits.join}"