Last active
August 29, 2015 14:24
-
-
Save mkowoods/3df94405eebe4ef3d9e6 to your computer and use it in GitHub Desktop.
Generic Shortest Path with Subway Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
----------------- | |
# User Instructions | |
# | |
# Write a function, subway, that takes lines as input (read more about | |
# the **lines notation in the instructor comments box below) and returns | |
# a dictionary of the form {station:{neighbor:line, ...}, ... } | |
# | |
# For example, when calling subway(boston), one of the entries in the | |
# resulting dictionary should be 'foresthills': {'backbay': 'orange'}. | |
# This means that foresthills only has one neighbor ('backbay') and | |
# that neighbor is on the orange line. Other stations have more neighbors: | |
# 'state', for example, has 4 neighbors. | |
# | |
# Once you've defined your subway function, you can define a ride and | |
# longest_ride function. ride(here, there, system) takes as input | |
# a starting station (here), a destination station (there), and a subway | |
# system and returns the shortest path. | |
# | |
# longest_ride(system) returns the longest possible ride in a given | |
# subway system. | |
# ------------- | |
# Grading Notes | |
# | |
# The subway() function will not be tested directly, only ride() and | |
# longest_ride() will be explicitly tested. If your code passes the | |
# assert statements in test_ride(), it should be marked correct. | |
def subway(**lines): | |
"""Define a subway map. Input is subway(linename='station1 station2...'...). | |
Convert that and return a dict of the form: {station:{neighbor:line,...},...}""" | |
station_map = {} | |
for line, station_str in lines.items(): | |
stations = station_str.split(' ') | |
for i in range(len(stations) - 1): | |
stat_a, stat_b = stations[i], stations[i + 1] | |
station_map.setdefault(stat_a, {}) | |
station_map.setdefault(stat_b, {}) | |
station_map[stat_a][stat_b] = line | |
station_map[stat_b][stat_a] = line | |
return station_map | |
boston = subway( | |
blue='bowdoin government state aquarium maverick airport suffolk revere wonderland', | |
orange='oakgrove sullivan haymarket state downtown chinatown tufts backbay foresthills', | |
green='lechmere science north haymarket government park copley kenmore newton riverside', | |
red='alewife davis porter harvard central mit charles park downtown south umass mattapan') | |
def ride(here, there, system=boston): | |
"Return a path on the subway system from here to there." | |
_succ = lambda state : system[state] | |
_is_goal = lambda state : state == there | |
return shortest_path_search(start = here, | |
successors = _succ, | |
is_goal = _is_goal) | |
def longest_ride(system): | |
""""Return the longest possible 'shortest path' | |
ride between any two stops in the system.""" | |
longest_ride = (0, []) | |
stations = system.keys() | |
for i in range(len(stations)): | |
for j in range(i, len(stations)): | |
path = ride(stations[i], stations[j], system) | |
tmp_ride = (len(path), path) | |
if tmp_ride > longest_ride: | |
longest_ride = tmp_ride | |
return longest_ride[1] | |
def shortest_path_search(start, successors, is_goal): | |
"""Find the shortest path from start state to a state | |
such that is_goal(state) is true.""" | |
if is_goal(start): | |
return [start] | |
explored = set() # set of states we have visited | |
frontier = [ [start] ] # ordered list of paths we have blazed | |
while frontier: | |
path = frontier.pop(0) | |
s = path[-1] | |
for (state, action) in successors(s).items(): | |
if state not in explored: | |
explored.add(state) | |
path2 = path + [action, state] | |
if is_goal(state): | |
return path2 | |
else: | |
frontier.append(path2) | |
return [] | |
def path_states(path): | |
"Return a list of states in this path." | |
return path[0::2] | |
def path_actions(path): | |
"Return a list of actions in this path." | |
return path[1::2] | |
def test_ride(): | |
assert ride('mit', 'government') == [ | |
'mit', 'red', 'charles', 'red', 'park', 'green', 'government'] | |
assert ride('mattapan', 'foresthills') == [ | |
'mattapan', 'red', 'umass', 'red', 'south', 'red', 'downtown', | |
'orange', 'chinatown', 'orange', 'tufts', 'orange', 'backbay', 'orange', 'foresthills'] | |
assert ride('newton', 'alewife') == [ | |
'newton', 'green', 'kenmore', 'green', 'copley', 'green', 'park', 'red', 'charles', 'red', | |
'mit', 'red', 'central', 'red', 'harvard', 'red', 'porter', 'red', 'davis', 'red', 'alewife'] | |
assert (path_states(longest_ride(boston)) == [ | |
'wonderland', 'revere', 'suffolk', 'airport', 'maverick', 'aquarium', 'state', 'downtown', 'park', | |
'charles', 'mit', 'central', 'harvard', 'porter', 'davis', 'alewife'] or | |
path_states(longest_ride(boston)) == [ | |
'alewife', 'davis', 'porter', 'harvard', 'central', 'mit', 'charles', | |
'park', 'downtown', 'state', 'aquarium', 'maverick', 'airport', 'suffolk', 'revere', 'wonderland']) | |
assert len(path_states(longest_ride(boston))) == 16 | |
return 'test_ride passes' | |
print test_ride() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment