In [1]:
#!/usr/bin/env python
from collections import deque
class KeypadDirector(object):
def __init__(self, keypad=((3,6,9),(2,5,8),(1,4,7))):
# Keypad is oriented 90 degrees to the left so 2d tuple follows basic X,Y coordinate order
self.keypad = keypad
# Find and start at "5" on the keypad always
for x, y, v in [(x, y, v)
for x, row in enumerate(keypad)
for y, v in enumerate(row)]:
if str(v) == '5':
break
self.coords = [x,y]
# Movements dictionary to lookup the change in position on the keypad
self.movements = dict(R=(-1, 0), U=(0, -1), L=(1, 0), D=(0, 1))
def follow_directions(self, commands):
try:
for command in commands:
movement = self.movements[command]
self.x += movement[0]
self.y += movement[1]
except KeyError:
raise ValueError('Commanded to move in %r direction' % command)
return self.key
@property
def y(self):
return self.coords[1]
@y.setter
def y(self, value):
try:
if value >=0 and self.keypad[self.coords[0]][value] is not None:
self.coords[1] = value
except IndexError:
pass
@property
def x(self):
return self.coords[0]
@x.setter
def x(self, value):
try:
if value >=0 and self.keypad[value][self.coords[1]] is not None:
self.coords[0] = value
except IndexError:
pass
@property
def key(self):
return self.keypad[self.coords[0]][self.coords[1]]
def __str__(self):
return 'Keypad at (%i,%i), key %i' % (
self.x, self.y, self.key)
print KeypadDirector()
In [2]:
# Example, 1985 for puzzle 1, 5DB3 for puzzle 2
input_str = """ULL
RRDDD
LURDL
UUUUD"""
In [3]:
#input_str = """DUURRDRRURUUUDLRUDDLLLURULRRLDULDRDUULULLUUUDRDUDDURRULDRDDDUDDURLDLLDDRRURRUUUDDRUDDLLDDDURLRDDDULRDUDDRDRLRDUULDLDRDLUDDDLRDRLDLUUUDLRDLRUUUDDLUURRLLLUUUUDDLDRRDRDRLDRLUUDUDLDRUDDUDLLUUURUUDLULRDRULURURDLDLLDLLDUDLDRDULLDUDDURRDDLLRLLLLDLDRLDDUULRDRURUDRRRDDDUULRULDDLRLLLLRLLLLRLURRRLRLRDLULRRLDRULDRRLRURDDLDDRLRDLDRLULLRRUDUURRULLLRLRLRRUDLRDDLLRRUDUDUURRRDRDLDRUDLDRDLUUULDLRLLDRULRULLRLRDRRLRLULLRURUULRLLRRRDRLULUDDUUULDULDUDDDUDLRLLRDRDLUDLRLRRDDDURUUUDULDLDDLDRDDDLURLDRLDURUDRURDDDDDDULLDLDLU
#LURLRUURDDLDDDLDDLULRLUUUDRDUUDDUDLDLDDLLUDURDRDRULULLRLDDUDRRDRUDLRLDDDURDUURLUURRLLDRURDRLDURUDLRLLDDLLRDRRLURLRRUULLLDRLULURULRRDLLLDLDLRDRRURUUUDUDRUULDLUDLURLRDRRLDRUDRUDURLDLDDRUULDURDUURLLUDRUUUUUURRLRULUDRDUDRLLDUDUDUULURUURURULLUUURDRLDDRLUURDLRULDRRRRLRULRDLURRUULURDRRLDLRUURUDRRRDRURRLDDURLUDLDRRLDRLLLLRDUDLULUDRLLLDULUDUULLULLRLURURURDRRDRUURDULRDDLRULLLLLLDLLURLRLLRDLLRLUDLRUDDRLLLDDUDRLDLRLDUDU
#RRDDLDLRRUULRDLLURLRURDLUURLLLUUDDULLDRURDUDRLRDRDDUUUULDLUDDLRDULDDRDDDDDLRRDDDRUULDLUDUDRRLUUDDRUDLUUDUDLUDURDURDLLLLDUUUUURUUURDURUUUUDDURULLDDLDLDLULUDRULULULLLDRLRRLLDLURULRDLULRLDRRLDDLULDDRDDRURLDLUULULRDRDRDRRLLLURLLDUUUDRRUUURDLLLRUUDDDULRDRRUUDDUUUDLRRURUDDLUDDDUDLRUDRRDLLLURRRURDRLLULDUULLURRULDLURRUURURRLRDULRLULUDUULRRULLLDDDDURLRRRDUDULLRRDURUURUUULUDLDULLUURDRDRRDURDLUDLULRULRLLURULDRUURRRRDUDULLLLLRRLRUDDUDLLURLRDDLLDLLLDDUDDDDRDURRL
#LLRURUDUULRURRUDURRDLUUUDDDDURUUDLLDLRULRUUDUURRLRRUDLLUDLDURURRDDLLRUDDUDLDUUDDLUUULUUURRURDDLUDDLULRRRUURLDLURDULULRULRLDUDLLLLDLLLLRLDLRLDLUULLDDLDRRRURDDRRDURUURLRLRDUDLLURRLDUULDRURDRRURDDDDUUUDDRDLLDDUDURDLUUDRLRDUDLLDDDDDRRDRDUULDDLLDLRUDULLRRLLDUDRRLRURRRRLRDUDDRRDDUUUDLULLRRRDDRUUUDUUURUULUDURUDLDRDRLDLRLLRLRDRDRULRURLDDULRURLRLDUURLDDLUDRLRUDDURLUDLLULDLDDULDUDDDUDRLRDRUUURDUULLDULUUULLLDLRULDULUDLRRURDLULUDUDLDDRDRUUULDLRURLRUURDLULUDLULLRD
#UURUDRRDDLRRRLULLDDDRRLDUDLRRULUUDULLDUDURRDLDRRRDLRDUUUDRDRRLLDULRLUDUUULRULULRUDURDRDDLDRULULULLDURULDRUDDDURLLDUDUUUULRUULURDDDUUUURDLDUUURUDDLDRDLLUDDDDULRDLRUDRLRUDDURDLDRLLLLRLULRDDUDLLDRURDDUDRRLRRDLDDUDRRLDLUURLRLLRRRDRLRLLLLLLURULUURRDDRRLRLRUURDLULRUUDRRRLRLRULLLLUDRULLRDDRDDLDLDRRRURLURDDURRLUDDULRRDULRURRRURLUURDDDUDLDUURRRLUDUULULURLRDDRULDLRLLUULRLLRLUUURUUDUURULRRRUULUULRULDDURLDRRULLRDURRDDDLLUDLDRRRRUULDDD"""
In [4]:
# Solution for problem 1
k = KeypadDirector(keypad = ((3,6,9),
(2,5,8),
(1,4,7)))
password = []
# Read in the input directions, appending to password to be joined later
for command in input_str.splitlines():
location = str(k.follow_directions(command))
password.append(location)
#print location
print ''.join(password)
In [5]:
# Solution for problem 2, different kind of keypad
k = KeypadDirector(keypad = ((None, None, 9, None, None),
(None, 4, 8, 'C', None),
(1, 3, 7, 'B', 'D'),
(None, 2, 6, 'A', None),
(None, None, 5, None, None)))
password = []
# Read in the input directions, appending to password to be joined later
for command in input_str.splitlines():
password.append(str(k.follow_directions(command)))
print ''.join(password)