1
+ # Problem: https://exercism.org/tracks/ruby/exercises/robot-simulator
2
+
3
+ # Solution
4
+ class Robot
5
+ attr_accessor :bearing
6
+ DIRECTIONS = [ :north , :east , :south , :west ]
7
+
8
+ def orient ( direction )
9
+ raise ArgumentError unless %i[ east west north south ] . include? ( direction )
10
+ @bearing = direction
11
+ end
12
+
13
+ def turn_right
14
+ @bearing = DIRECTIONS [ ( DIRECTIONS . index ( @bearing ) +1 ) %4 ]
15
+ end
16
+
17
+ def turn_left
18
+ @bearing = DIRECTIONS [ ( DIRECTIONS . index ( @bearing ) -1 ) %4 ]
19
+ end
20
+
21
+ def at ( x , y )
22
+ @x = x
23
+ @y = y
24
+ end
25
+
26
+ def coordinates
27
+ [ @x , @y ]
28
+ end
29
+
30
+ def advance
31
+ case @bearing
32
+ when :north
33
+ @y +=1
34
+ when :south
35
+ @y -=1
36
+ when :east
37
+ @x +=1
38
+ when :west
39
+ @x -=1
40
+ else
41
+ raise ArgumentError
42
+ end
43
+ end
44
+ end
45
+
46
+ class Simulator
47
+ def instructions ( instruction_str )
48
+ commands = [ ]
49
+ instruction_str . chars . each do |instruction |
50
+ case instruction
51
+ when "R"
52
+ commands . push ( :turn_right )
53
+ when "L"
54
+ commands . push ( :turn_left )
55
+ when "A"
56
+ commands . push ( :advance )
57
+ else
58
+ raise ArgumentError
59
+ end
60
+ end
61
+ commands
62
+ end
63
+
64
+ def place ( robot , **kwargs )
65
+ robot . at ( kwargs [ :x ] , kwargs [ :y ] )
66
+ robot . orient ( kwargs [ :direction ] )
67
+ end
68
+
69
+ def evaluate ( robot , instruction_str )
70
+ commands = instructions ( instruction_str )
71
+ commands . each do |command |
72
+ robot . send ( command )
73
+ end
74
+ end
75
+ end
76
+
77
+ # Solution 2
78
+ class Robot
79
+ INCREMENTS = { north : [ 0 , 1 ] , east : [ 1 , 0 ] , south : [ 0 , -1 ] , west : [ -1 , 0 ] }
80
+ VALID_BEARINGS = INCREMENTS . keys
81
+
82
+ attr_reader :bearing , :coordinates
83
+
84
+ def orient ( direction )
85
+ raise ArgumentError unless VALID_BEARINGS . include? direction
86
+ @bearing = direction
87
+ end
88
+
89
+ def turn_right
90
+ @bearing = VALID_BEARINGS [ VALID_BEARINGS . index ( @bearing ) + 1 ] || :north
91
+ end
92
+
93
+ def turn_left
94
+ @bearing = VALID_BEARINGS [ VALID_BEARINGS . index ( @bearing ) - 1 ]
95
+ end
96
+
97
+ def at ( *coordinates )
98
+ @coordinates = coordinates
99
+ end
100
+
101
+ def advance
102
+ @coordinates = @coordinates . zip ( INCREMENTS [ @bearing ] ) . map { |a , b | a + b }
103
+ end
104
+ end
105
+
106
+ class Simulator
107
+ COMMANDS = { 'L' => :turn_left , 'R' => :turn_right , 'A' => :advance }
108
+
109
+ def instructions ( command_str )
110
+ command_str . chars . map { |cmd | COMMANDS [ cmd ] }
111
+ end
112
+
113
+ def place ( robot , x : 0 , y : 0 , direction : :north )
114
+ robot . at ( x , y )
115
+ robot . orient ( direction )
116
+ end
117
+
118
+ def evaluate ( robot , command_str )
119
+ instructions ( command_str ) . each { |cmd | robot . send ( cmd ) }
120
+ end
121
+ end
0 commit comments