首页 > > 详细

辅导skyroute留学生、讲解Python程序语言、辅导Python设计、program讲解 讲解留学生Processing|讲解Pyth

FILE: skyroute.py
Introduction
Vancouver’s public metro system has asked you to help create a program to help commuters get from one
landmark to another. You’ll be building out “SkyRoute,” a routing tool that uses breadth-first search, depthfirst
search, and Python dictionaries to accomplish this feat. For the purposes of this project, you can assume
that it takes the same amount of time to get from each station to each of its connected neighboring stations.
First, tab through the files you have at your disposal:
graph_search.py has the bfs() and dfs() functions implemented in Python
vc_metro.py contains a graph of all stations in the Vancouver metro system
vc_landmarks.py contains a dictionary of Vancouver landmarks mapped to their nearest metro
station(s)
landmark_choices.py contains a dictionary of letters of the alphabet mapped to landmarks to make it
easier for users to make a selection
We import the files listed above here.
In [1]:
import graph_search
import vc_metro
import vc_landmarks
import landmark_choices
First, define a variable that we’ll be using throughout our program:
landmark_string should be a string that joins all of the landmarks together, each with its corresponding
letter of the alphabet from landmark_choices on a new line.
In [ ]:
Below landmark_string , define a function greet() with no parameters. In the function body, print out
two statements:
"Hi there and welcome to SkyRoute!"
"We'll help you find the shortest route between the following Vancouver landmarks:\n" + landmark_string
See how that landmark_string already came in handy?
In [ ]:Outside of greet() , define a new function skyroute() which will contain our full program. It won’t take
any parameters. Inside, call greet() .
Great! Now, try calling skyroute() at the bottom of the file, save your code, and enter python3
skyroute.py in your console to see what happens.
In [ ]:
Let’s jump out of the skyroute() function body and define a few new functions. Add pass into the function
body for each for the moment.
First, set_start_and_end() , which takes two parameters: start_point and end_point . This will
handle setting the selected origin and destination points.
Next, get_start() , which takes no parameters. It will be used to request an origin from the user.
Finally, get_end() , which is also void of parameters. Can you guess how it will be used?
In [ ]:
In the function body of set_start_and_end() , remove pass and check if start_point has a value other
than None . If it does, we already have an origin and destination, but the user wants to make a change.
Luckily, we’re prepared for that!
Collect input from the user using the following question and assign the response to a new variable
change_point:
"What would you like to change? You can enter 'o' for 'origin', 'd' for 'destination',
or 'b' for 'both': "
In [ ]:
Before we handle change_point , add an else condition in case no start_point has been set yet.
Inside the else condition:
set start_point equal to get_start()
set end_point equal to get_end()
Below the else condition (outside of it, but still inside the function), employ multiple return to return
both start_point and end_point from the function.
In [ ]:Now let’s get back into that if statement and tackle change_point. Below your definition of change_point ,
we’ll add a little control flow to handle the input:
If change_point is equal to "b" , then reset start_point and end_point using get_start()
and get_end() respectively.
Use elif to check if change point is "o" . If it is, then only reset start_point .
Use another elif statement to check if change point is "d" . If it is, then only reset end_point .
Use else to handle cases in which the user typed some other value. Inside the condition, print "Oops,
that isn't 'o' , 'd' , or 'b' ..." and recursively call set_start_and_end() on start_point and
end_point so that the user has a chance to try again.
In [ ]:
Try calling set_start_and_end() with None and None as the arguments and printing the result. Save
your code and enter python3 skyroute.py in the terminal to see what happens!
After all that work, why are you getting back "None, None" ? Oh right, you still need to set up
get_start() and get_end() ! The good news is that these functions are very similar.
Make sure to remove your call of set_start_and_end() .
In [ ]:
Let’s begin with get_start() . In the function body, remove pass and set start_point_letter equal to
user input from the question "Where are you coming from? Type in the corresponding letter: " .
We need to make sure make sure the user entered a real landmark name! Use a conditional to check if
start_point_letter exists as a key in landmark_choices .
If it does, set start_point equal to landmark_choices[start_point_letter] and return
start_point from the function.
In [ ]:
Add an else condition. In the body of the else condition, print "Sorry, that's not a landmark we
have data on. Let's try this again..." and recursively return a call of get_start() so that the
user gets a chance to get it right.
In [ ]:Set up get_end() in exactly the same way as you set up get_start() except with:
end_point in lieu of start_point
a recursive call of get_end() in lieu of get_start() "Ok, where are you headed? Type in the
corresponding letter: " instead of "Where are you coming from? "
In [ ]:
Try calling set_start_and_end() with None and None as the arguments and printing the result to the
console again. Did you get the right return values?
In [ ]:
Let’s build a wrapper function for the bulk of the program that we can use to:
get and set the origin and destination
call search to get the recommended route
allow users to search for another route To accomplish this, define a new function new_route() , which
takes two parameters: start_point and end_point . Give both a default value of None .
We do this because start_point and end_point may need to be defined for the first time or redefined
upon subsequent new_route() calls.
In [ ]:
In the new_route() function, set start_point and end_point equal to the function call of
set_start_and_end() with start_point and end_point as arguments.
In [ ]:
We have the function to set the origin and destination for our route. It’s time for a bit of breadth-first search to
spice things up and actually find the best route between those selected points!
Outside new_route() , define a new function get_route() which takes two parameters. Can you guess
what they are?
In [ ]:You may be itching to run bfs() on your start and end points (with the vc_metro graph). You can even try
it out, but if you run that code, you won’t get what you’re looking for. That is, unless what you’re looking for
happens to be a pile of errors.
Why all the errors?
Your start_point and end_point are landmarks, not metro stations. And if you take a look at
vc_landmarks.py again, you’ll see that some landmarks have more than one metro station. In order to get
the metro stations closest to to each landmark, you’ll need to access them through the vc_landmarks
dictionary.
Inside the get_route() function, create a variable start_stations and set it equal to
vc_landmarks[start_point] . This should grab a set of at least one metro station.
In [ ]:
Below start_stations , set another variable end_stations using the same logic.
In [ ]:
Because some landmarks have more than one station, there is sometimes more than one route between
landmarks. That means it’s our job to collect all of the shortest routes between stations and then compare
them based on path length.
For example, you could get from Herald Square in Midtown, NYC to Codecademy in Soho, NYC in a few
ways. You can start at 34th Street-Herald Square station and end either at Prince Street station or BroadwayLafayette
station.
The shortest path between 34th Street-Herald Square and Prince Street is five stops. The shortest path
between 34th Street-Herald Square and Broadway-Lafayette is two stops. If we compare those two possible
shortest routes, we have a clear shortest route.
To collect our shortest routes for comparison, create an empty list called routes under the stations
variables you just defined in get_route() .
In [ ]:
Ready to get your loop on? To get each combination, we can use a Python for loop to loop through each
start_station in start_stations and then, inside, loop through each end_station in
end_stations .
In [ ]:Inside the inner for loop, create a variable route and set it equal to a call of bfs() on vc_metro as the
graph, start_station as the start vertex, and end_station as the end vertex.
In [ ]:
Check if route exits. If it does, add this new shortest route to the routes list that you created. If you’ll
recall, this route returned from bfs() is a Python list that represents the path.
In [ ]:
Outside of both loops but still inside the get_route() function, we can now get our shortest route from our
routes list based on list length using a nifty Python trick:
min(list_name, key=len)
Save the final resulting shortest route to a variable shortest_route and then return shortest_route
from the function.
In [ ]:
Let’s see if the get_route() function does what it’s supposed to! Call get_route() with two landmark
names (you can grab these from the vc_landmarks keys) and print the result. Now save your code and in
the console enter: python3 skyroute.py .
In [ ]:
It’s time to take this awesomeness back to the new_route() function. In your new_route() function body,
create a variable shortest_route and set it equal to get_route() called on the start_point and
end_point variables you defined above.
In [ ]:
As you may have noticed, shortest_route is in a format that isn’t all that user-friendly. Let’s change that!
Create a new variable called shortest_route_string set to a string that has each station from
shortest_route on a new line. Hint:
some_string = '\n'.join(list_name)In [ ]:
Below this new string variable, print the following to the console:
"The shortest metro route from {0} to {1} is:\n{2}".format(start_point,
end_point, shortest_route_string)
In [ ]:
At this point, we have a pretty solid tool. Call new_route() in the body of skyroute() below
greeting() . Now try calling skyroute() in your console. Pretty cool, right?
In [ ]:
What if someone wants to know about more than one route? Let’s give them a chance to get that info before
the program abruptly closes down. Under the final print statement in new_route() , collect user input for the
question "Would you like to see another route? Enter y/n: " and save it to the variable again .
In [ ]:
Check if again is equal to “y” . If it is, make a recursive call of new_route() with the current values of
start_point and end_point passed in.
In [ ]:
After a few calls, it might be helpful for the user to see the list of landmarks again. Above the recursive call of
new_route() , call a function show_landmarks() without any arguments.
In [ ]:
Outside of new_route() , define show_landmarks() without any parameters. In the function body, use a
new variable see_landmarks to capture user input for the the question "Would you like to see the
list of landmarks again? Enter y/n: ".
In [ ]:On the next line (still in the show_landmarks() function), check if see_landmarks is equal to “y” . If it
is, print out the landmark_string for the user.
In [ ]:
Now our function will loop as long as our user wants to look up new directions! Pretty neat, right? But we still
have a bit of an abrupt ending. Let’s fix that. Outside all your functions, create another function goodbye() .
In it, print "Thanks for using SkyRoute!" , giving our user some pleasant parting words.
In [ ]:
Add a call of goodbye() at the end of the skyroute() function body. Test out your function in the console
to see how it works!
In [ ]:

联系我们
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 99515681 微信:codinghelp
程序辅导网!