1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
class Keypad
  MAP = [%w[ . . 1 . . ],
         %w[ . 2 3 4 . ],
         %w[ 5 6 7 8 9 ],
         %w[ . A B C . ],
         %w[ . . D . . ]]

  attr_reader :x, :y

  def initialize
    @x, @y = 0, 2
  end

  def button
    MAP[y][x]
  end

  def <<(dir)
    delta = case dir
            when ?U
              [0, 1]
            when ?D
              [0, -1]
            when ?L
              [-1, 0]
            when ?R
              [1, 0]
            else
              raise "unexpected direction: '#{dir}'"
            end
    next_x = x + delta[0]
    next_y = y - delta[1]

    next_x = [[4, next_x].min, 0].max
    next_y = [[4, next_y].min, 0].max

    @x, @y = next_x, next_y if MAP[next_y][next_x] != ?.
  end
end

if __FILE__ == $0
  keypad = Keypad.new
  code = DATA.read.lines.map {|line|
    line.strip.chars.each do |char|
      keypad << char
    end
    keypad.button
  }
  puts code.join
end

require 'minitest'
# require 'minitest/autorun'

class TestDay2 < Minitest::Test
  def test_day2
    keypad = Keypad.new
    assert_equal ?5, keypad.button

    'ULL'.chars.each do |char|
      keypad << char
    end
    assert_equal ?5, keypad.button

    'RRDDD'.chars.each do |char|
      keypad << char
    end
    assert_equal ?D, keypad.button

    'LURDL'.chars.each do |char|
      keypad << char
    end
    assert_equal ?B, keypad.button

    'UUUUD'.chars.each do |char|
      keypad << char
    end
    assert_equal ?3, keypad.button
  end
end

__END__