---
tags: Homeworks-Summer21
---
# Homework 5: Fun with Scala
**Due Date: Wednesday July 7th, anwhere-on-earth time (Thursday, July 8th, 8 a.m. EDT)**
**This homework will be graded, however, it will be weighed less than your other homeworks.**
## Mid-Semester Feedback
The semester is halfway over --- if you wish, we would love to hear any mid-semester feedback you might have for us this summer. It has been a joy to have you all in CS18 and we thank you for all of your hard work so far! We want to make the second half of the semester even better than the first, so we would appreciate any feedback if you have it. **This form is completely anonymous and optional**.
[Fill out the mid-semester feedback form here!!](https://forms.gle/qA1dGNoFMH81e5bXA)
## Functional Programming Assignment Requirement
:::info
**Important Note:**
You **MUST** use the functional aspects of Scala to get full credit for this assignment. This means that you should strictly **never** mutate anything *or* reassign names (i.e., you cannot use the Scala keyword `var` in this assignment).
:::
As a reminder, some techniques we used in functional programming are:
* higher-order-functions (called Higher Order Procedures in CS17)
* here's the [Scala documentation for `List`s](https://www.scala-lang.org/api/2.13.3/scala/collection/immutable/List.html) where you can find how to use familiar higher-order-functions (`filter`, `foldLeft`, etc.) and some new ones that may help.
* here's a link to [the class 20 notes](https://cs18-summer-2021.github.io/static/classes/20/20scalaIntro.pdf) which shows examples of using `map`, `foldLeft`, and anonymous procedures.
* pattern matching
* here's a link to [Scala's documentation on match cases](https://docs.scala-lang.org/tour/pattern-matching.html) --- you can ignore the sections on sealed classes and case classes for now.
* here's a link to [the class 20 notes](https://cs18-summer-2021.github.io/static/classes/20/20scalaIntro.pdf) which shows examples of using the keyword `match` in Scala.
* recursion
* taking functions as arguments and returning them as values
These are provided to jog your memory and you may find that some of these techniques are not necessary for this assignment!
Additionally, keep in mind that while you cannot reassign names, you *can* make Scala `val`s that are the result of performing various operations. You are also welcome to use basic object properties like `length` and `isEmpty` (as these can be done easily in a functional way).
## Learning Objectives
By the end of this homework, you will be able to:
* Develop classes that protect how their data is used through access modifiers and appropriate choice of provided methods
* Develop a collection of examples and tests that exercise key behavioral requirements aspects of a problem
* Write programs that behave as expected based on a provided description or collection of test cases
* Use concrete examples, invariants, hand tracing, and debugging to explore or explain how a program works
## Assignment Link
Here is the [Github classroom link](https://classroom.github.com/a/DI2HNDbE).
This homework is in Scala. Check out our [IntelliJ Setup Guide](https://hackmd.io/Cq7UQr7JQmardJnHt71Ryg?view) if you're having trouble running the Scala code.
If you're having trouble with IntelliJ, check out our [IntelliJ Common Problems](https://hackmd.io/webHvA8yTCqGOAKXYgrI_A) handout.
Please make sure to read [our gradescope submission guide](https://hackmd.io/jC-SEMn_RpiGqMH_EhsDMw) before handing in your assignment!
## Handing In
You should hand in the following files for this assignment:
* Shopping Cart
* `CartItem.scala`, containing `class CartItem`.
* `Checkout.scala`, containing `class Checkout`.
* Vote Counting
* `Vote.scala`, containing `class Vote`.
* `VoteCounting.scala`, containing `class VoteCounting`.
* Earthquake
* `MaxHzReport.scala`, containing `class MaxHzReport`.
* `Earthquake.scala`, containing `class Earthquake`.
* Testing
* `Homework5TestSuite.scala`, containing `class Homework5TestSuite`
To hand in your files, submit them to Gradescope.
- Submit your files to the Homework 5: Implementation submission
- Submit `Homework5TestSuite.scala` to the Homework 5: Testing submission.
Once you have handed in your homework, you should receive an email, more or less immediately, confirming that fact. If you don't receive this email, try handing in again, or ask the TAs what went wrong.
**Note:** If your code does not work with the autograder, you will be penalized. If there are any complications, follow these steps:
* Make sure that your Testing submission passes the wheat. If it doesn't, you should use the autograder output and the message in the failed autograder test to debug your test suite.
* If your test suite passes the wheat, run your implementation against your test suite. If this crashes, you should fix your solution code so that it is compatible with your test suite.
* If you are still having issues, please reach out to us at TA Hours or by Ed.
## The Hunt Continues...
:::spoiler Optional theme material
After following the digital Ed paper trail in HW4 to the previous clue, you realize that you've been neglecting your normal non-clue-hunting life, and need to restock on utilities! You head to your favorite online hardware store, *The Blueno Depot*, and notice a small paragraph at the bottom of the home page...
*The trail of clues you've seen thus **far**
Cheeky, witty, and never **subpar**
Once hidden **away**
Now in full **display**....
Open to find the most (☞゚ヮ゚)☞ [**bizarre**](https://drive.google.com/file/d/19AKWJEqIZSanwR1DOPaR5u1vvx0MrPSr/view?usp=sharing)*
(Try running your Grep implementation from last homework on the bolded words above on this text file! String together the numbers you get, and go to tinyurl.com/yournumberhere)
For example, if your outputs were [1], [2], [3], [4], [5] the link would be tinyurl.com/12345
:::
## Shopping Cart
An online hardware store applies discounts during checkout. A shopping cart is a list of the items being purchased. Each item has a name (a `String` like “100-count nails”) and a price (a `Double` like 6.95), which is greater than 0. Design a `class Checkout` that has a method, `totalCost`, which consumes a shopping cart and produces the total cost of the cart after applying the following two discounts:
* If the cart contains at least $50 worth of nails, take 15\% off the cost of **JUST** the nails (nails are any item with a name that is exactly "nails")
* If the cart contains at least two smoke alarms, take $10 off the total of the cart (a smoke alarm is any item whose name is exactly "smoke alarm"). You can assume that the total cost of 2 smoke alarms will always be at least $10.
The input shopping cart is represented as a`List` (in Scala) of objects of a class named `CartItem`. The constructor for `CartItem` takes a `String` name and a `Double` cost. For example, assuming we have the CartItem and Checkout classes defined:
```scala=
val apple = new CartItem("apple", 0.75)
val cape = new CartItem("cape", 50.01)
val cart : List[CartItem] = List(apple, cape)
val check = new Checkout
check.totalCost(cart) //returns 50.76
```
<!-- Java version of the code snippet -->
<!--
```java=
CartItemJava apple = new CartItemJava("apple", 0.75);
CartItemJava cape = new CartItemJava("cape", 50.01);
ArrayList<CartItemJava> cart = new ArrayList<CartItemJava>();
cart.add(apple);
cart.add(cape);
CheckoutJava check = new CheckoutJava();
check.totalCost(cart); // returns 50.76
```
-->
**Task:** In **Scala**, create the `CartItem` class, which takes in a `String` name and a `Double` cost in its constructor. You do not have to error check for invalid input.
**Task:** In **Scala**, create the `Checkout` class, which has the `totalCost` method. This method should take in an `List` of `CartItem` objects, and return the total `Double` cost of all the objects, applying the 2 discounts above as necessary. You can assume that an empty cart (i.e., an empty `List`) has cost 0.0.
You do not need to round or otherwise manipulate your answers to two decimal points. Just take the total as it is computed.
:::info
**Note:** Reminder that you **MUST** use the functional aspects of Scala to get full credit for this problem. See the [note at the top of the page](https://hackmd.io/@cs18-spring-2021/hwk5-summer#Functional-Programming-Assignment-Requirement) for clarification on what this means.
:::
**Task:** Test your `Checkout` class exhaustively in `Homework5TestSuite.scala`. See [the class 20 notes](https://cs18-summer-2021.github.io/static/classes/20/20scalaIntro.pdf) for details on how to use the tester in Scala if you are unsure how to do so.
## Vote Counting
Before Blueno left campus, he assembled the mystical, brilliant, Nobel-prize-wining, most-sensational CS18 Team of Theme. Their job: direct worthy CS18 students to his treasure. In fact, they have been crafting clever — again, *Nobel-prize-winning* — limericks to guide you to the clues you've found thus far! The CS18 Team of Theme employs a democratic process, where every member votes for who will write the next earth-shattering limerick.
Their voting system receives as input a List of Votes, represented as a class in Scala. Your task is to create a class which can tally a list of votes, and return percentages of votes for each candidate.
**Task:** In **Scala**, create a class `Vote`, which takes two `Strings`: a candidates's name (representing *who the vote is for*) and the voter's current location in its constructor, e.g.
```scala=
val annie = new Vote("Jack", "Providence")
val jack = new Vote("Annie", "Roof of the CIT")
val morgann = new Vote("Annie", "Hamad International Airport" )
val peter = new Vote("Grace", "Swaggy Ratty")
val grace = new Vote("Annie", "The One Really Nice Bathroom in Granoff")
val harshini = new Vote("Grace", "Breakout Room 3")
```
*Note: the names and locations can be any `String` - these are just examples.*
**Task:** In **Scala**, create a class `VoteCounting`, which takes in its constructor a `List[Vote]`.
Now that you have your class, you want to be able to count the votes for a particular person, and return a double representing the percent of votes that this candidate received.
The CS18 Team of Theme decided that people in Providence are no longer allowed to write limericks. They would like to disqualify any voters who put "Providence" as a location.
**Task:** Create a `candPercentage` method in your `VoteCounting` class, which takes in a `String` for a candidate's name, and returns a `Double` for the percent of votes (e.g. 0.45) received. This percent calculation should not count any votes whose locations are exactly "Providence" (including in the total votes), and should not exceed 1.0.
An empty list should return 0.0 for any input candidate, as should a list containing only votes whose locations are "Providence". Additionally, an input for a candidate who is not in the list or whose only votes have "Providence" as a location should output 0.0.
:::info
**Note:** Reminder that you **MUST** use the functional aspects of Scala to get full credit for this problem. See the [note at the top of the page](https://hackmd.io/@cs18-spring-2021/hwk5-summer#Functional-Programming-Assignment-Requirement) for clarification on what this means.
:::
**Task:** Exhaustively test the `VoteCounting` class in `Homework5TestSuite.scala`.
## Earthquake
Geologists want to monitor a local mountain for potential earthquake activity and have installed a sensor to track seismic (vibration of the earth) activity. The sensor inserts markers among the measurements to indicate the date of the measurement. The sequence of values coming from the sensor looks as follows: `20151004 200 150 175 20151005 0.002 0.03 20151007 130 0.54 20151101 78 ...`
The 8-digit numbers are dates (in year-month-day format). Numbers between 0 and 500 inclusive are vibration frequencies (in Hz). This example shows readings of 200, 150, and 175 on October 4th, 2015 and readings of 0.002 and 0.03 on October 5th, 2015. There are no data for October 6th (sometimes there are problems with the network, so data go missing). You can make the following assumptions about the data.
* All data are dates (8-digits) or frequencies (between 0 and 500 inclusive)
* The data are in order by dates (so a later date never appears before an earlier one in the sequence)
* All data are from the same year.
* The dates will always be 8-digit numbers in the format above (and starting with a non-0 digit).
* You may also assume that every date is followed by at least one frequency (in other words, every date has at least one measurement).
* You may assume that each date appears at most once in the input.
**Task:** In **Scala**, create the `MaxHzReport` class, which takes in its constructor a date, which is an 8-digit `Double` in the same format as above, and a measurement, which is a `Double` representing the highest frequency recorded for that particular date. You may assume that the input is exactly as specified as above, and don't have to error check this. In addition, please add an `equals` method for the `MaxHzReport` class.
**Task:** In **Scala**, create the `Earthquake` class, which has a method `dailyMaxForMonth`. This method consumes a `List[Double]` of sensor data and a month (an `Int` between 1 and 12) and produces a `List[MaxHzReport]` of reports indicating the highest frequency reading for each day in that month. Only include entries for dates that are part of the data provided (so don't report anything for October 6th in the example shown above). Ignore data for months other than the given one. Each item in the `List` should be an instance of `MaxHzReport`.
For example, given the sequence of values above and the month 10 (for October), the resulting List should contain:
* MaxHzReport(20151004, 200)
* MaxHzReport(20151005, 0.03)
* MaxHzReport(20151007, 130)
**Hint:** You might find the functions `takeWhile` and `dropWhile` to be helpful. In particular, you can use these to strategically generate a `List[List[Doubles]]`. Start here on your attempts to solve this problem. The syntax for these methods looks like the following:
```scala=
val data : List[Double] = List(1.0,2.0,5.0,3.0,4.0)
// List(5.0,3.0,4.0)
val dataDrop : List[Double] = data.dropWhile(x => x < 5.0)
// List(1.0,2.0)
val dataTake : List[Double] = data.takeWhile(x => x < 5.0)
```
:::info
**Note:** Reminder that you **MUST** use the functional aspects of Scala to get full credit for this problem. See the [note at the top of the page](https://hackmd.io/@cs18-spring-2021/hwk5-summer#Functional-Programming-Assignment-Requirement) for clarification on what this means.
:::
**Hint:** Stuck on trying to get the month out of an 8 digit double? Try the following (though make sure that you understand each part of what's going on!):
```scala=
val date : Double = 19950331
val month : Int = (date.toInt/100) % 100 // Returns 3
```
**Task:** Exhaustively test the Earthquake class in `Homework5TestSuite.scala`.
## Getting Started
To brush up on Scala syntax before you start, revisit the lecture notes, or check out the Scaladocs [here](http://www.scala-lang.org/api/current/index.html).
Additionally, make sure to read the [Scala Style Guide](https://hackmd.io/@cs18-spring-2021/HkjsOGudO) and the [Scala Good Coding Practices](https://hackmd.io/@cs18-spring-2021/S1FuJmuOu), before getting started.
A good strategy for this assigment is to write the methods and classes in the order they appear in the handout (`CartItem`, `Checkout`, `Vote`, `VoteCounting`, `MaxHzReport`, `Earthquake`). Make sure to write some tests before and while you write your methods, to help solidify your understanding and improve test coverage.
## FAQ
**I can't access my fields! What should I do?**
If you want to turn constructor arguments into fields, you need to put`val` or `var` before them in the constructor. However, for this homework, you should only be using `val`. You will learn the difference between `val` and `var` in the future.
**I don't know why I'm having issues with my numbers!**
Be careful declaring whether a variable is a `Double` or an`Int`. Specifically, if you'll be doing arithmetic that depends on the accuracy of decimals or could be a decimal value, declare your `val` as a `Double` . There are two ways to do this. First, you can type annotate :
`val x: Double = 0`
Second, you can initialize your `Double` with a decimal point:
`val x = 0.0`
In both examples, `x` will have the value zero. Neither method is preferred.
---
*Please let us know if you find any mistakes, inconsistencies, or confusing language in this or any other CS18 document by filling out the (mostly) [anonymous feedback form](https://cs.brown.edu/courses/cs018/feedback)!*