A.10 python template # TODO; My functions
def main():
# TODO; Test my funct
A.10 python template # TODO; My functions
def main():
# TODO; Test my functions
pass
if __name__ == “__main__”:
main()
DD.10 Follow the instructions in A/DD.10 and record your designs for each of the problems in your Design Document. Make sure to:
List each design in a clearly marked section indicates which question the design belongs to.
For each design make sure to note any details about the question that are relevant to your design, such as the inputs, outputs, any required displays.
Also make sure to detail your tests including all inputs and outputs you’d expect to see.
Each problem should have a detailed plan which outlines step-by-step how you get the required outputs from the provided inputs.
If you divide any problem into smaller algorithms, make sure to detail all of the information for those designs as well.
As a rule of thumb, your designs should include enough detail that anyone else could take your design and implement the same solution without confusion. If you’re questioning if a design is clear enough, ask a TA if they understand your work!
A/DD.10
It’s tax season (boo)! While we’ve been rushing around getting everything ready to file that mess, we’ve noticed that we have quite a few receipts from eating out and ordering food — more than a few, really… Well, okay, there’s a ton of receipts here, perhaps too many. That has us wondering how much we spent on food during the last few months of last year. Instead of fighting with all that paper like some old-time accountant, we’ve decided to use the computer to do those calculations for us!
To start, we’ve already created several CSVs that contain data related to this task. Each of these CSVs has four columns that describe some data related to our purchase:
A unique location ID as an integer.
The subtotal of the purchase as a float.
The tax as a percentage from 0.0 to 1.0.
The amount we added as a tip.
Many receipts only had a little more information, so we have to go off of only these four pieces of data to determine what we’re interested in: the total we spend at each location. For each row in each of our receipt CSVs, we can calculate the total cost of that purchase using this formula:
total=subtotal+(subtotal×tax)+tiptotal=subtotal+(subtotal×tax)+tip
We frequent a few places, so expect multiple rows with duplicate IDs. We’ll need to design a way to account for this as we get the sum of our repeated purchases all under a single ID.
Having a whole bunch of numeric identifiers is fine, but weirdly abstract numbers are a computer thing, not a human thing, so we’ve gone through and found all of the proper names for a whole bunch of the identifiers. We’ve stored this data in another CSV file with two columns, one for the ID and the other for a string name. That CSV file will always have unique IDs for each row, but there might be more IDs than we have receipts. We are sure that our receipts will always have a valid entry on this list, so searching this list for a particular ID is how our program can determine the name of the location we care about when showing our report.
Speaking of, we’ve had some free time to write a function that prints our final data, which is already given below. We’ll want to modify that function so it writes to a text file instead so we can run our program many times with different receipts and see all of the details later.
Our task is this:
Complete the functions listed below to expose the true horror of how much we’ve spent on dining! Before starting our design, note the requirements for each function and the formats we should expect the CSVs to be in. Note that some information (or even the functions themselves) may be helpful for later functions!
Example Files:
The following are some example files you can use with your application. The “places.csv” can be used with load_locations, and the rest can be used with load_receipts and load_many_receipts.
places.csv
receipt_sep.csv
receipt_oct.csv
receipt_nov.csv
1.) Find (for a 2D list)
Design and implement the function find_2d, which will take a 2D list and a value to find in that 2D list. For every row, the value should be checked against the first entry in the list. Return the index of the first matching value; otherwise, return -1 if the value was not in the list. You may assume that if the input list has rows, it will always have rows of at least length one.
2.) Load Locations
Design and implement the function load_locations, which will take a filename to a locations CSV, read its data, and return a 2D list containing all of the identifiers and names of locations we expect to see in the receipts. The output 2D list should follow the same column order as the CSV.
3.) Load Receipts
Design and implement load_receipts, a function which will take a filename to one of our receipt CSV files, read its data, and will return a 2D list that contains the identifier for a locations and the total sum of all entries for that identifier in this single file. Note that many rows might have the same identifier, but our output list should properly sum all of those together into a single entry. For example, if the input to our function looks like this:
id,subtotal,tax_percent,tip
1111,20.00,0.05,5.00
2222,36.50,0.10,7.25
1111,10.00,0.05,3.00We expect to get a list that looks similar to:
[[1111, 39.5],[2222, 47.4]]4.) Load Many Receipts
We’ll want to make a function that is able to take several filenames for receipts and calls the previous function on each one, so design and implement load_many_receipts, which takes a list of receipt filenames along with the locations filename and does just that. This function shouldn’t return anything, and instead call the function below to save our calculations to a file. Be aware that we will have to merge the data from each call to load_receipts so that the location identifiers in one file don’t overwrite the data from another!
5.) Write Report
Finally, we’ll need to have a way to save our data. Thankfully, we’ve already done some of this with the write_report below, but we’ll need to change it so that it appends data to report.txt instead of just printing things out.
def write_report(fn: str, data: list[list], places: list[list]) -> None:
“””Writes out the final report for this set of data.
Args:
fn (str): The filename to append to.
data (list[list]): A 2D list of receipt record data.
places (list[list]): A 2D list of identifiers and locations names.
“””
# Print the very front of the record
print(“****************************************n”)
print(“Total Records:” + str(len(data)) + “n”)
# For each entry in the data list
for i in range(len(data)):
row = data[i]
# Print out the name of the location this row represents
print(places[find_2d(places, row[0])][1])
# Print out the total amount spent at this location
print(“t$” + str(row[1]) + “n”)Hints and Notes
You may assume that the CSV files will always start with their header row and will always contain data that follows the specified format.This means that you don’t have to worry about casts of the appropriate type failing when converting from strings.
Every location identifier seen in a receipt will be in the locations CSV at some point.
The receipt and location data loaded from the CSVs will not be in any particular order.
All input filenames will be valid.
You can use the provided write_report as-is while developing!
Errata
For the example given in load_receipts, previously the first row of data was being ignored instead of only the header row. Only the resulting value in the output was changed.