On Day 2 we need to get access to the bathroom protected by a locked door with a keypad.
Our keypad is just 9-digit simple thing:
1 2 3
4 5 6
7 8 9
We also have an input with instructions on which buttons to press:
ULL
RRDDD
LURDL
UUUUD
Each line represents one digit to press. We start on digit 5 and then we follow the instructions. So for first line we have ULL, which means up, left and left. So we go from 5 to 2 then 1 and again left, but we have no way to go more, so we stay at 1.
For next lines we start at the last position and continue the same procedure.
Here is my solution:
data = File.readlines("2.txt").map(&:strip).map { |line| line.split("") }
buttons = {
[0, 0] => 1,
[1, 0] => 2,
[2, 0] => 3,
[0, 1] => 4,
[1, 1] => 5,
[2, 1] => 6,
[0, 2] => 7,
[1, 2] => 8,
[2, 2] => 9
}
position = [1, 1]
def valid?(position)
(0..2).include?(position[0]) && (0..2).include?(position[1])
end
buttons = data.map do |row|
row.each do |move|
case move
when "U"
new_position = [position[0], position[1] - 1]
when "D"
new_position = [position[0], position[1] + 1]
when "L"
new_position = [position[0] - 1, position[1]]
when "R"
new_position = [position[0] + 1, position[1]]
end
if valid?(new_position)
position = new_position
end
end
buttons[position]
end
puts buttons.join
We have buttons
hash mapping positions on the keypad to button values, we have valid?
method checking if our position is within the keypad and we have starting position set to [1, 1] which is the button 5.
Then we just iterate through our input, we follow the instructions updating our position and checking if it is valid. After processing each line we store button value in the array. And finally we print it out.
In second part we have more advanced keypad that looks like this:
1
2 3 4
5 6 7 8 9
A B C
D
We still start at button 5 and apply the same logic. We can use the previous code with just updated keypad mapping like this:
@buttons = {
[0, -2] => 1,
[-1, -1] => 2,
[0, -1] => 3,
[1, -1] => 4,
[-2, 0] => 5,
[-1, 0] => 6,
[0, 0] => 7,
[1, 0] => 8,
[2, 0] => 9,
[-1, 1] => "A",
[0, 1] => "B",
[1, 1] => "C",
[0, 2] => "D"
}
And valid?
method can just check if position is in the hash. If not, it is invalid position:
def valid?(position)
@buttons.key?(position)
end
Here is the full solution:
data = File.readlines("2.txt").map(&:strip).map { |line| line.split("") }
@buttons = {
[0, -2] => 1,
[-1, -1] => 2,
[0, -1] => 3,
[1, -1] => 4,
[-2, 0] => 5,
[-1, 0] => 6,
[0, 0] => 7,
[1, 0] => 8,
[2, 0] => 9,
[-1, 1] => "A",
[0, 1] => "B",
[1, 1] => "C",
[0, 2] => "D"
}
position = [-2, 0]
def valid?(position)
@buttons.key?(position)
end
results = data.map do |row|
row.each do |move|
case move
when "U"
new_position = [position[0], position[1] - 1]
when "D"
new_position = [position[0], position[1] + 1]
when "L"
new_position = [position[0] - 1, position[1]]
when "R"
new_position = [position[0] + 1, position[1]]
end
if valid?(new_position)
position = new_position
end
end
@buttons[position]
end
puts results.join