In [1]:
#!/usr/bin/env python
from collections import deque

class Taxi(object):
    def __init__(self, x=0, y=0, direction='N'):
        # Absolute location starting from 0,0 (origination point)
        self.location = [0,0]
        self.visited_locations = []
        self.repeated_locations = []
        # North, West, South, East.
        # Rotate left vs right for correct cardinal direction being element 0
        self.cardinal_directions = deque([(0,1,'N'), (-1, 0,'E'), (0,-1,'S'), (1,0,'W')])
    
    def set_location(self, x, y):
        self.location = [x,y]
        
    def set_direction(self, new_direction):
        new_direction = new_direction.upper()
        if new_direction not in 'NSEW':
            raise ValueError('%r is not N, S, E or W (cardinal direction)' % new_direction)
        # Start out pointing north
        self.cardinal_directions = deque([(0,1,'N'), (-1, 0,'E'), (0,-1,'S'), (1,0,'W')])
        turns = dict(N=0, E=1, S=2, W=3)
        self.turn_right(turns[new_direction])

    def turn_left(self, number_turns=1):
        self.cardinal_directions.rotate(-1 * number_turns)
    
    def turn_right(self, number_turns=1):
        self.cardinal_directions.rotate(1 * number_turns)
    
    def step_forward(self, steps=1):
        for i in range(steps):
            self.location[0] += self.direction[0]
            self.location[1] += self.direction[1]
            if tuple(self.location) in self.visited_locations:
                self.repeated_locations.append(tuple(self.location + [self.direction[2], abs(self.x) + abs(self.y)]))
            self.visited_locations.append(tuple(self.location))
    
    def follow_directions(self, command):
        # Takes the form of "L232" for "turn left and walk 232 steps"
        if command[0] == 'L':
            self.turn_left()
        elif command[0] == 'R':
            self.turn_right()
        else:
            raise ValueError('Commanded to turn to the %r relative direction' % command[0])
        self.step_forward(int(command[1:]))
    
    @property
    def x(self):
        return self.location[0]
    
    @property
    def y(self):
        return self.location[1]
    
    @property
    def direction(self):
        return self.cardinal_directions[0]
    
    def __str__(self):
        return 'Taxi at (%i,%i) facing %s, %i steps from (0,0)' % (
            self.x, self.y, self.direction[2], abs(self.x) + abs(self.y))

print Taxi()


Taxi at (0,0) facing N, 0 steps from (0,0)

In [2]:
input_dir = "R2, L1, R2, R1, R1, L3, R3, L5, L5, L2, L1, R4, R1, R3, L5, L5, R3, L4, L4, R5, R4, R3, L1, L2, R5, R4, L2, R1, R4, R4, L2, L1, L1, R190, R3, L4, R52, R5, R3, L5, R3, R2, R1, L5, L5, L4, R2, L3, R3, L1, L3, R5, L3, L4, R3, R77, R3, L2, R189, R4, R2, L2, R2, L1, R5, R4, R4, R2, L2, L2, L5, L1, R1, R2, L3, L4, L5, R1, L1, L2, L2, R2, L3, R3, L4, L1, L5, L4, L4, R3, R5, L2, R4, R5, R3, L2, L2, L4, L2, R2, L5, L4, R3, R1, L2, R2, R4, L1, L4, L4, L2, R2, L4, L1, L1, R4, L1, L3, L2, L2, L5, R5, R2, R5, L1, L5, R2, R4, R4, L2, R5, L5, R5, R5, L4, R2, R1, R1, R3, L3, L3, L4, L3, L2, L2, L2, R2, L1, L3, R2, R5, R5, L4, R3, L3, L4, R2, L5, R5"

In [3]:
t = Taxi()
# Read in the input directions
for command in input_dir.split(', '):
    t.follow_directions(command)

In [4]:
# Solution for problem 1
print t


Taxi at (147,-87) facing W, 234 steps from (0,0)

In [5]:
# Solution for problem 2
print t.repeated_locations[0]


(16, -97, 'W', 113)