| Introduction |
This programming assignment is designed to ensure that you know how to use
combinations of Python's most important data types to model and
compactly write code that solves a few different programming problems.
The kind of abstract thinking that goes into modeling solutions to these
programming problems, with these data types (and iteration over them), is
critical to your development as programmers.
There are two parts to this assignment. In each you will be asked to write a module that contains a few functions and a script at the bottom, which ties these functions together to solve the problem. You should download the program6 project folder and use it to create an Eclipse project. You will create each module in this project, and submit each module separately in Checkmate. The project folder contains no modules, but it does contain all the data files you need to test/debug you modules. Only one student should submit all parts of the the assignment, but both student's names should appear in the comments at the top of each submitted .py file. It should look something like # Romeo Montague, Lab 1 # Juliet Capulet, Lab 1 # We certify that we worked cooperatively on this programming # assignment, according to the rules for pair programmingPlease turn in each program as you finish it, so that I can accurately assess the progress of the class as a whole during this assignment. Print this document and carefully read it, marking any parts that contain important detailed information that you find (for review before you turn in the files). The code you write should be as compact and elegant as possible, using appropriate Python idioms. You can use either dict or defaultdict, and you will need to use split to convert a string you read from a file into a list of names. Although the example strings are all one-character, your code should work for any length strings. You should familiarize yourselves with the safe_open function in the goody module and all the functions in the prompt module, both of which you should have installed in your courselib folder as part of the Eclipse/Python installation. Recall how to use the sep and end parameters in the print function. Finally, reread the section on Time Management from Programming Assignment 0 before starting this assignment. |
| Problem #1: Reachability |
Problem Summary:
Input and OutputRead a file of pairs of node names (representing edges) in a directed graph, building a dict whose key is a str source node and whose value is a set of str destination nodes that are each reachable from the source node key. We write this annotation as {str : {str}}
Two nodes appear on each line: first the source node, then the destination
node, with these node names separated by one semicolon character.
For example, the input file graph1.txt contains the following
lines (which could appear in this order, or any other):
Print the graph, one source node per line (the source nodes are printed
alphabetically) followed by the set of all the destination nodes that the
source can immediately reach.
The graph above would print as
Note that the source nodes are sorted alphabetically, but the set
of desintation nodes does not have to be sorted:
in fact it makes no sense to talk about sorted sets; we could talk
about a sorted list whose contents came from a set.
Note that because node g is not a source node (it is only a
destination node), it does not appear first on any line (and appears only
in the sets for source nodes d and f.
Note that there are multiple data files for this program: graph1.txt,
graph2.txt and graph3.txt; test/debug your program on
the first file; when you are done, test it on the last two.
Draw the graph represented by each for to ensure that your code correctly
prints it and computes the nodes reachable from any source node (which you
can do by eyeballing the graphs: they are small).
Repeatedly prompt the user for a starting node in the graph (until quit
is entered) and compute and print all the nodes that are reachable from it by
following edges in the graph.
Reject any node not present in the graph.
An example interaction (processing the graph above) might be
I am supplying these number of lines not as requirements, but ballpark estimate
of the amount of code you should write.
Here is the basic algorithm for computing reachability; it is simple to explain
and not (very) complicated to implement.
But, you have to understand these instructions and carefully translate them into
Python.
You should hand-simulate this algorithm using the graph above, and verify that
it produces the results you expect before coding it.
If you know what recursion is, you might be tempted to use it; but please
don't: unless recursion is done very carefully, it will run forever on graphs
with cycles: one of the input files is a graph with cycles.
Print the set containing all these node labels.
When debugging this algorithm, print the set and list after every
interesting change, or use the debugger to see how these change.
|
| Problem #2: Instant Runoff Voting |
Problem Summary:
During the first ballot, votes are counted for each of the candidates according to the rankings of the voters. Then the candidate(s) with the fewest number of votes are removed from the election: if more than one candidate receives the least number of votes, they all are removed from the election. During the second ballot, votes are tallied for the remaining candidates (there are at least 1 fewer candidates); if a voter's first ranked candidate is still in the election, then that candidate should receive the vote; if a voter's first ranked candidate is not still in the election, then his/her second ranked candidate should receive the vote; but if his/her second ranked cnadidate has been removed from the election, then his/her third ranked candidate should receive the vote ...). This ballot process continues until either 1 candidate remains, or 0 candidates remain (meaning that all the previous candidates tallied the same number of votes and therefore were all removed). Input and OutputRead a file of voters and their ranking of the candidates, separated by semicolons, building a dict whose key is each voter and whose value is a list of candidates ranked by that voter (they appear in the file in order, from most favorite to least favorit) We write this annotation as {str : [str]}
For example, the input file votepref1.txt contains the following
lines (which could appear in this order, or any other):
Print all the associations in this dict, one per line (the voters are
printed alphabetically) using the following form.
Each line contains the voter and his/her complete ranking of the candidates.
For example, the file above would produce:
Note that the voter names are sorted alphabetically, but the list of preference appear the same order they appeared in the file. There are multiple data files for this program: votepref1.txt, votepref2.txt and votepref3.txt; test/debug your program on the first file; when you are done, test it on the rest.
Start with all the candidates.
Evaluate the ballot to determine how many votes each candidate received.
Print this vote count two ways: sorted alphabetically and sorted numerically
(in decreasing order).
Remove the candidate(s) receiving the fewest votes, and repeat this process
until only one or no candidates remain.
Finally, print the outcome of the election: a single candidate winner or a tie.
An example interaction (processing the graph above) might be
If you have any questions about how instant runoff voting works (these rules are a bit subtle), please post questions on the forum; you can include examples and what-if questions as long as you don't write code. Functions and Script
Sample InteractionThe program, as specified, will have the following interaction: user-typed information appears in italics. Your output should match this one. Enter file with voter preferences: votepref1.txt
Voter Preferences
A -> ['X', 'Y', 'Z']
B -> ['Y', 'Z', 'X']
C -> ['Y', 'Z', 'X']
D -> ['Z', 'Y', 'X']
E -> ['Z', 'Y', 'X']
Vote count on ballot #1 with candidates (alphabetically) = {'Z', 'Y', 'X'}
X -> 1
Y -> 2
Z -> 2
Vote count on ballot #1 with candidates (numerical) = {'Y', 'X', 'Z'}
Y -> 2
Z -> 2
X -> 1
Vote count on ballot #2 with candidates (alphabetically) = {'Y', 'Z'}
Y -> 3
Z -> 2
Vote count on ballot #2 with candidates (numerical) = {'Y', 'Z'}
Y -> 3
Z -> 2
Winner is {'Y'}
You can also try processing the votepref2.txt file (which leads to a No winner result) and votepref3.text. |