--- title: Homework 6 tags: Homeworks-F22, 2022 --- # Homework 6: Python Basics **Due:** Tuesday November 15, 2022 at 11:59PM ET. ## Big Picture The goal of this assignment to give you practice with the basics of writing list-processing programs in Python. It mostly follows what we've done in class, while also showing a couple of useful Python built-in functions. Everything you need for this will have been covered by the end of class on Wednesday. ## Setup and Handin ### Setup You should have VSCode set up from the first week of the course. In case you don't, refer to the [VSCode Installation and Setup Guide](https://hackmd.io/lBJMV4rCSIuJ1P7RzvJSiQ?view) - Make a new file called `test_hw6.py` and write `import pytest` at the top of that file. All the tests you create should be written there. - Create a python file called `hw6_code.py` to include your code. ### Handin - Download your code file and make sure it is called `hw6_code.py`. Hand in your work on [Gradescope](https://www.gradescope.com/courses/423395). - Download your test file and make sure it is called `test_hw6.py`. Hand in your work on [Gradescope](https://www.gradescope.com/courses/423395). - Answer the questions on voting technology in the HW6-SRC area on [Gradescope](https://www.gradescope.com/courses/423395). ### Remember your resources! <!-- - [Gearup](https://www.gradescope.com/courses/357203/assignments/2000617) --> - [Python documentation](https://docs.python.org/3.9/) - [TA hours](http://cs.brown.edu/courses/csci0111/spring2022/calendar.html) - [EdStem](https://edstem.org/us/courses/27983/discussion/) - [Course syllabus](https://hackmd.io/@cs111/syllabus-f22) - [Python Testing and Clarity Guide](https://hackmd.io/@cs111/python_guide) ## The Assignment -- Election Time :::warning Make sure to only use Python concepts we've talked about in lecture when solving these problems. In particular, if you have other Python knowledge of other techniques, don't use them here if you want full credit. In particular, don't use the built-in Python `count` function. That defeats the point of the problems. ::: It's election season, and we're going to write some programs to tally votes. We'll represent a vote as a single `string` containing the name of the person or thing that got voted for. We'll represent the collection of votes recorded by a single voting machine as a `list` of votes (list of `string`). :::warning For every function we ask you to write, you should have a corresponding testing function in `test_hw6.py`. Name each test function the same as the original function but with `test_` prepended. In other words, the tests for a function `check_votes` would be in a function called `test_check_votes`. ::: ### Part 1: Basic Vote Counting **Task 1:** Write a function called `name_matches`. It should take in a `vote` (string) and a `name` (string). It should return a boolean indicating whether the vote is for the given name, regardless of how either vote or the name have been capitalized. *Note: You can convert a string `s` to lowercase in Python by writing `s.lower()`. As in Pyret, you have Boolean operators `and`, `or`, and `not`.* **Task 2:** In `hw6_code.py`, write a function called `any_votes_for` that takes in a name and a list of votes and returns a `boolean` indicating whether any of the votes were for the given name (case insensitive). **Task 3:** In `hw6_code.py`, write a function `count_votes_for` that takes in a name and a list of votes. It should return the number of votes that were for the given name (case insensitive). **Task 4:** In `hw6_code.py`, write a function called `got_more_votes` that determines which of two names got more votes. Your function should take in two names and a list of votes. It should return the name that got more votes (case insensitive). If there is a tie, return the string `“tie”`. ### Part 2: Recording Votes **Task 5:** In `hw6_code.py`, write a function to record a new vote. Your function should be called `record_vote`, and take in a list of votes, and a string representing a new vote. It should add the new vote to the end of the list of votes. The function **should not return anything!** ### Part 3: Election Integrity With people concerned about the validity of the election results, the decision has been made to run some checks against the votes to see if they appear plausible. One issue is that write-in votes can be ambiguous. Imagine an election in which two people with the first name "Ruth" have been trying to get elected. Some votes have come through for "Ruth Achebe", some for "Ruth Flynn", and some for just "Ruth". The "Ruth" votes need to get handled for accurate results. Someone has proposed counting "Ruth" votes that have a last name, using the presence of a space in the name string to indicate whether a vote has both a first and a last name. **Task 6:** Write a function `clean_votes` that takes a list of votes and returns a new list of votes containing only the votes from the original list that contain at least one space (represented by the string `" "`). **Task 7:** Write a `test_clean_votes` function (in the `test_hw6.py` file) that explores various scenarios in which this specific approach would and would behave as we expected. If you think there are situations that the "check for space" situation would handle poorly for a goal of proper vote counting, include a test case that illustrates the undesirable behavior (write your test to pass what `clean_votes` actually does, but include a comment about why the result is undesirable.) In general, pay particular attention to the set of strings and vote lists that you include in your test lists. We'll be looking to see how well you explore the space of names and vote lists when grading this question. Even with removing the single-name votes, people are still concerned that there might be weird issues in the votes. To help find them, they want to be able to sort the list of votes in different ways to make it easier to look for inconsistencies in spelling, etc. In Python, sorting a list numerically or alphabetically is as easy as writing `sorted(theList)` (where `theList`) is the list you want to sort. If you instead want to provide your own criterion, such as the length of the name you use the following form: ```=python sorted(theList,key=keyFun) ``` where `theList` is the list to sort and `keyFun` is a function that takes a single item of the list and returns a value (like a number) that gets used for sorting. :::spoiler An example of custom sorting with `sorted` and `keyFun` Here's the code to sort a list of strings by the lengths of the strings. The order in the list is preserved for items of the same length. ``` def key_fun(elem: str) -> int: return len(elem) >>> sorted(["Rhea", "does", "love", "sorting", "lists"], key=key_fun) ['Rhea', 'does', 'love', 'lists', 'sorting'] ``` *(Note that since string length is an integer, `sorted` defaults to the integer string sorting behavior of sorting the elements in increasing order)* ::: <br> **Task 8:** Write a function `sort_phrase_len` that takes a list of strings (each of which may have spaces) and sorts the phrases in order of how many words they have (from fewest to most). *Note: Similar to Pyret, Python has a function `split` that converts a string into a list of words around a separator character. For example,* ``` 'llamas'.split('a') is ['ll', 'm', 's'] ``` Given prior trends in the district where the votes have been cast, there are expectations on what percentage of the vote specific candidates might get (within a margin of error). We'll write a program to check whether a candidate's votes are within such an expected range. **Task 9:** In `hw6_code.py`, write a function `check_percent` that takes the name of a candidate, a list of votes, an expected percentage (decimal within 0-1), and an error tolerance (decimal). The function returns one of "higher", "in-range", or "lower". It returns "in-range" if the percentage of votes that the candidate received is within the error tolerance (inclusive) of the expected percentage. Otherwise, "higher" or "lower" is returned based on where the actual percentage lands relative to the error tolerance. *Hint: This is an excellent problem on which to practice planning. We're not having you develop the plan explicitly, but we strongly suggest that you develop one on paper in case you need to get help from the TAs.* ### Part 4: Voting Technology Voting is a topic for which people are reasonably concerned about representation, access, and accuracy (among other things). Not surprisingly, there are many arguments and proposals regarding how to properly use computing technology as part of elections: should we vote on computers so they can count ballots? allow voting online? use digital scanners to process votes marked on paper? And so on. Each option offers benefits and risks around participation in, and accuracy of, elections. **Task 10:** For this question, go to the form in the `HWK 6 SRC` assignment in Gradescope. You'll be asked to answer the following questions: - Before you do any of the linked readings: - write down what you see as the benefits and challenges/risks of conducting statewide elections on (electronic) voting machines on which people mark their choices (then the machine tallies the vote using programs) - write down what you see as the benefits and challenges/risks of conducting national elections online/over the internet - Read this brief article on the use of [internet voting in Estonia](https://time.com/5541876/estonia-elections-electronic-voting/). (Nothing to write for this one) - VerifiedVoting.org is an organization of experts on election security and election technology. Pick **one** of the five topics on their [issues page](https://verifiedvoting.org/issues/), and read their summary of the issue (on the issue-specific page marked by a "More" button). Fill in the Gradescope question that asks you to identify a nuance about election security that came up around that issue. (You're of course welcome to read about more of the issues if you want!) ## Check Block - Paste the following code at the end of your `hw6_code.py` file. If `All required methods exist!` prints, you're good to go! If `One of the required methods is missing or named incorrectly` prints, you are either missing a method, or have named one incorrectly. ``` try: assert "name_matches" in dir() assert "any_votes_for" in dir() assert "count_votes_for" in dir() assert "got_more_votes" in dir() assert "record_vote" in dir() assert "clean_votes" in dir() assert "sort_phrase_len" in dir() assert "check_percent" in dir() print("All required methods exist!") except: print("At least one of the required methods is missing or named incorrectly") ``` ## Double Check You Have Completed All Tasks! Remember to submit all of your work on Gradescope! The files should be submitting are: :::spoiler `hw6_code.py` **Tasks to be submitted in `hw6_code.py`:** **Part 1** * Task 1: ```name_matches``` function * Task 2: ```any_votes_for``` function * Task 3: ```count_votes_for``` function * Task 4: ```got_more_votes``` function **Part 2** * Task 5: ```record_vote``` function **Part 3** * Task 6: ```clean_votes``` function * Task 8: ```sort_phrase_len``` function * Task 9: ```check_percent``` function ::: :::spoiler `test_hw6.py` **Tasks to be submitted in `test_hw6.py`:** * Task 1: ```test_name_matches``` function * Task 2: ```test_any_votes_for``` function * Task 3: ```test_count_votes_for``` function * Task 4: ```test_got_more_votes``` function **Part 2** * Task 5: ```test_record_vote``` function **Part 2** * Task 7: ```test_clean_votes``` function * Task 8: ```test_sort_phrase_len``` function * Task 9: ```test_check_percent``` function ::: ## Theme Song [Year 3000](https://youtu.be/HSry5-qfVFs) by Jonas Brothers