---
title: Homework 6
tags: Homeworks-F21, 2021
---
# Homework 6: Python Basics
**Due:** Wednesday November 17, 2021 at 9:00PM ET.
<!--  -->

## Setup and Handin
### Setup
- This is our first time using Pycharm! Yay! You have a choice: you can either create a new project in Pycharm for ALL your files, or create a new project for each homework. **Remember to write `import pytest` at the top of your file!**
- [Pycharm Installation and Project Setup](https://hackmd.io/@cs111/HyMA5VInQ)
- [Python Testing and Clarity Guide](https://hackmd.io/@cs111/python_guide)
### Handin
- Download your file and make sure it is called `hw6_code.py`. Hand in your work on [Gradescope](https://www.gradescope.com/courses/302007).
### Remember your resources!
- [Python documentation](https://docs.python.org/3.7/)
- [TA hours](http://cs.brown.edu/courses/csci0111/fall2021/calendar.html)
- [EdStem](https://edstem.org/us/courses/12806/discussion/)
- [Course syllabus](https://hackmd.io/@cs111/syllabus-f21)
## The Assignment
:::warning
If you know how to solve any of these problems using techniques you've learned outside of 111, don't! Make sure to only use Python concepts we've talked about in class.
:::
Create a new Python file called `hw6_code.py`.
**Task:** Write `import pytest` at the top of your `hw6_code.py` file.
### Apollo 111's Election
An election is happening in CS111's mission control. The team is trying to decide who should man their next mission to space, and Space Election Official Ryan needs help counting the votes.
For the following, you can assume a vote is just the name of a candidate (though capitalization might be inconsistent!)
1. **Task:** Write a function `name_matches` that takes a `vote` (string) and a `name` (string) and returns a boolean indicating whether the vote is for the given name, regardless of how the vote and name have been capitalized (that is, ignore case).
*Note:* You can lowercase a string `s` in Python by writing `s.lower()` (where `s` gets replaced by the string you want to lowercase). As in Pyret, you have Boolean operators `and`, `or`, and `not`.
2. **Task:** Write a function `any_votes_for` that takes a `name` (string) and `votes` (list of votes) and returns a boolean indicating whether any votes were for the given name (case insensitive).
3. **Task:** Write a function `count_votes_for` that takes a `name` (string) and a `votes`, a list of votes, and returns the number of votes that were for the given name (case insensitive).
4. **Task:** Write a function `got_more_votes` that takes two names, `name_one` and `name_two`, and `votes`, a list of votes, and returns the name that got more votes (case insensitive). If there is a tie, return the string `“Tie”`.
5. **Task:** Write a function `record_vote` that takes in `votes`, a list of votes, and `new_vote`, a new vote, and adds the vote to the end of the list. This function should not return anything!
6. **Task:** Write a function `percentage_votes` that takes a name and a list of votes and returns the percentage of votes that match (case insensitive) the given name. You should return the percent in decimal form (i.e. if the name matches 90% of the votes, return 0.9). Please round to the nearest tenth. Don't forget to consider the case where someone has no votes (or where there are no votes)!
:::spoiler **Rounding help!**
You can round a number in Python using the `round` function. The `round` function has two arguments, the first being the number to round and the second representing how many decimal places to have. Here are a few examples:
```
# If you'd like to round to the nearest whole number
# Note: this will still produce a decimal not an Int
round(1.3446, 0) # produces 1.0
round(1.5111, 0) # produces 2.0
round(1.7934, 0) # produces 2.0
# If you'd like to round to the nearest tenth
round(1.3446, 1) # produces 1.3
round(1.5111, 1) # produces 1.5
round(1.7934, 1) # produces 1.8
# If you'd like to round to the nearest hundreth
round(1.3446, 2) # produces 1.34
round(1.5111, 2) # produces 1.51
round(1.7934, 2) # produces 1.79
round(1.799, 2) # produces 1.8
```
:::
8. **Task:** Write a function `test_votes` to test your vote functions. In particular, think about how to test `record_vote`. Run `test_votes()` to make sure all your tests pass and your functions work as expected.
*Note:* Any time you are returning a name, it may be returned lowercased or uppercased. Our test suite is case insensitive, so returning `"Kenny"` will be treated the same as `"kenny"` and `"KENNY"`. Same applies for functions that return lists. `["Ken","Kenny"]` will be treated the same as `["ken","KENNY"]`.
:::spoiler What `is` means in Python
*Note:* What `is` means in Python, you can also use the keyword `is` in lieu of `==`! `is` checks whether two items are the same item in memory, not just if they have the same value. You can find an example [here](https://www.w3schools.com/python/ref_keyword_is.asp).
:::
## Sorting Lists in Python
Here we have a lot of information to help with these questions. They'll be quite difficult to do without reading these first.
:::spoiler String slicing
To do many of the following problems, you will need to do something called *string slicing*. String slicing is the Python equivalent of Pyret's `string-substring`, but winds up being a lot more powerful.<br>
Let's say you have the string `str = "Beep!"`. Just like in Pyret, strings in Python are **0-indexed:**
- The "B" is at **index 0**
- The "e"s are at **indices 1 and 2**
- The "p" is at **index 3**
- The "!" is at **index 4**
To access the characters at those indices, use the notation: `str[index]`. For example,
```
>>> str[0]
"B"
>>>str[4]
"!"
```
If you want to slice a string into a substring of *more than one character*, use the notation: `str[start:end]` where `start` represents the first index of the substring (inclusive) and `end` represents the last index of the substring (exclusive). For example,
```
>>> str[0:5]
"Beep!"
>>> str[1:4]
"eep"
>>> str[2:3] # note that this is equivalent to str[2]
"e"
>>> str[2:2] # no characters in range, so this outputs the empty string
""
```
That's all you need to know for this assignment, but Python has a few additional shortcuts for string slicing that might be useful in the long run:
- If you **leave off the start or end index**, Python assumes you want to start at 0 and end at the end of the string:
```
>>> str[:3] # equivalent to str[0:3]
"Bee"
>>> str[3:] # equivalent to str[3:5]
"p!"
>>> str[:] # equivalent to str[0:5]
"Beep!"
```
- **Negative numbers** let you index from the end of a string
```
>>> str[-1] # equivalent to str[4]
"!"
>>> str[-5] # equivalent to str[0]
"B"
>>> str[-3:-1] # equivalent to str[2:4]
"ep"
```
:::
:::spoiler Basic sorting
Python has a useful and customizable sorting function that operates on lists. In this section, we will explore how to use it.
The simplest version of the function is `sorted(lst: list)`, which takes in a list and sorts it in ascending order.
- Lists of integers are sorted numerically
- Lists of strings are sorted alphabetically
- Lists of booleans are sorted with all Falses before all Trues
For example:
```
>>> sorted([1,5,3,1])
[1,1,3,5]
>>> sorted(["bc", "abc", "d", "aa", "aaa"])
['aa', 'aaa', 'abc', 'bc', 'd']
>>> sorted([False, True, True, False, True])
[False, False, True, True, True]
```
To sort a list in descending order, add the input `reverse=True` to the function call. Here are the examples from above but sorted in reverse:
```
>>> sorted([1,5,3,1], reverse=True)
[5,3,1,1]
>>> sorted(["bc", "abc", "d", "aa", "aaa"], reverse=True)
['d', 'bc', 'abc', 'aaa', 'aa']
>>> sorted([False, True, True, False, True], reverse=True)
[True, True, True, False, False]
```
*Note:* Notation like `reverse=True` is used for optional inputs to a function, a concept we did not see in Pyret. Since an optional input might not be provided, we need the `<name>=` part to indicate which optional parameter is being used.
:::
:::spoiler Custom sorting
In most cases, default sorting is enough. However, what if you want to sort a list in a specific, custom way? To do so, add the input `key=my_fun` where `my_fun` represents a function that takes in a single list element. `my_fun` is called on each element in the list, and **its output** determines the sort order.
Let's take a look at a concrete example. The following function takes in a string and returns its length:
```
def key_fun(elem: str) -> int:
return len(elem)
```
With `key_fun` defined, we can do the following to sort the list by string length:
```
>>> 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 sorting the elements in increasing order)*
:::
### Emergency Organization
Just as the results of the election are about to go out, Space Election Official Ryan drops all of the ballots on the floor.
For all of the following functions, you can assume that **all names have at least three letters**. This means that none of your tests cases should have names less than three letters.
1. **Task:** Write a function `first_three_letters(name: str, votes: list)` that takes in a candidate name and all votes and returns a list of all votes for candidates with the same first three letters in their name as `name` (regardless of capitalization).
2. **Task:** Write a function `test_first_three` to test `first_three_letters`.
3. **Task:** Write a function `sort_a(votes: list)` that returns `votes` sorted alphabetically by the first letter in candidate's names.
4. **Task:** Write a function `test_a` to test `sort_a`.
5. **Task:** Write a function `sort_b(votes: list)` that returns `votes` sorted alphabetically by the second letter in candidate's names. You can assume all strings in `votes` will be at least two characters long.
6. **Task:** Write a function `test_b` to test `sort_b`.
## SRC -- Reflecting on Project 1
We’ve been discussing situations in which data can be collected (e.g., from your car) or interpreted (e.g., the meta-data discussion from lecture) in ways that can have consequences for entities about whom information is obtained. Breaking it down, impacts from data can arise from multiple dimensions, such as:
- what data get **collected** in the first place (which variables are collected, whether populations are representative),
- how data are **processed** or combined (by programs), and
- what **inferences** can get drawn from data (by humans or computers)
In addition, every scenario that involves data also has **stakeholders**, which are entities that can be impacted (positive or negatively) based on that data. For example, with a restaurant review application, stakeholders include diners, restaurant owners, and the local communities that might get more or less business based on reviews.
For this assignment, we want you to do a stakeholder and data impacts analysis around whichever dataset (CO2, bikeshare, grocery stores) you used for project 1. Specifically:
- Make a list of 3-5 stakeholders that could be impacted positively or negatively by someone using this dataset.
- For each stakeholder, list one or two concrete impacts that the dataset could have on them; for each impact, explain whether it comes from the collection, processing, or inference from the dataset.
Review your collection of impacts: Which seem addressable by programmers? Which by policies or laws? Which are solely in the hands of users? The goal here is for you to start to develop some strategies for thinking about data impacts based on the different uses of data and potential interactions with programs.
*Put your answers to these in a single multi-line string at the bottom of your code file, as shown below. Please include line breaks to help your graders.*
```
"""this is my analysis
of stakeholders and impacts
of project 1 data
"""
```
## Theme Song
[Closing Time](https://www.youtube.com/watch?v=EAS-pvQ06s4) by Semisonic
------
> Brown University CSCI 0111 (Fall 2021)
> Do you have feedback? Fill out [this form](https://forms.gle/BuehRpxWnX97xYB68).