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()


Keypad at (1,1), key 5

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)


1985

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)


5DB3