Due: Friday, July 14 at 6pm (submit through Canvas)
To practice developing and testing functions that process lists
Collaboration Policy: You may work on this assignment with others. Include a collaboration statement describing how you did the work.
Put your answers to these questions in a file named votes.arr.
For this assignment, you will write some functions that lie at the heart of running elections. There are different methods for counting ballots in elections. This assignment explores two. In our elections, everyone indicates their first and second choice candidates. Some elections will count only the first-choice votes, while others do a weighted combination of the first-choice and second-choice votes.
Two tables will provide the data for an election:
A ballot is a table with (at least) two columns named candidate and party.
A vote-record is a table with columns named choice1 and choice2. Each row records a single vote for these two candidates.
Starting from this setup, do the following exercises:
Write a function num-votes-for that takes a choice (a string) and list of choices (strings) and returns the number of times that the given choice is in the list.
Sometimes, people vote for "write-in" candidates who were not on the ballot. Develop a function called write-ins that consumes a vote-record (Table) and a ballot (Table) and produces a list of choices that received votes but were not candidates on the ballot. The returned list should not have duplicates.
Testing such a function can be tricky if you can’t predict the order in which the write-in candidates will appear. One way to do this is to write examples in the following style:
L.member(write-ins(votes-cast, ballot), "Lucia") is true
L.length(write-ins(votes-cast, ballot)) is 2
This checks that specific names are in the returned list, without caring what order they are in.
Hint: You will likely want to write two functions for this: one function takes a list of choices and a list of known names and computes the items from the first list that are not in the second. The write-ins function can call the first function with data as extracted from the table.
Write a function tally-most-votes that consumes a list of choices and a vote-record and returns a list of lists. Each inner list contains a choice and the number of points earned by that choice when counting each choice1 vote as 1 point (and ignoring the choice2 votes).
A sample tally might look like:
[list: [list: "Ali", 5], [list: "Carmen", 3]]
(indicating that Ali got 5 points and Carmen got 3).
Write a function tally-pref-votes that consumes a list of choices and a vote-record and returns a list of lists. Each inner list contains a choice and the number of points earned by that choice when counting each choice1 vote as 3 points and each choice2 votes as 1 point. Tallies have the same structure as in the previous question.
Design an example vote-record in which different choices would win under each of the two counting methods. You don’t have to write programs to compute winners. Just provide a single table named votes-diff-result that would yield (a) a unique winner under each method (no ties) that is (b) different under each method.
You do NOT need to use the material from Wednesday about accumulators or passing functions as arguments as part of this homework (though you may if you wish). This isn’t meant to be complicated. I just want to make sure that everyone has had some experience writing list functions going into lectures next week.
In grading, we will look at your examples/tests, code structure, and code presentation. We expect you to follow the list template when appropriate (unless you are using a built-in list iterator like map or filter, which you are welcome to use if you wish).
Remember to include the collaboration statement.
If you want to check whether your file has the same names as our grading scripts will look for, insert the following code at the bottom of your file. This simply looks for the names and types that we stipulated in the assignment. If one of these checks fails, fix your code, not these checks.
fun col-name-test(table): |
select choice1, choice2 from table end |
end |
|
check: |
is-function(num-votes-for) |
is-function(write-ins) |
is-function(tally-most-votes) |
is-function(tally-pref-votes) |
col-name-test(votes-diff-result) |
end |
Create a directory named votes-hwk. Inside the directory, put a single Pyret file named votes.arr. Submit a zip of the votes-hwk directory. Even though you are submitting only one file, we need the directory to set up the scripts that will run some correctness checks against your homework.
Make sure you follow these directory and file names exactly, or we won’t be able to grade your work.