---
title: Homework 3
tags: Homeworks-S25
---
# Homework 3: Testing and Tables
**Due:** Monday, September 29th at 11:59 PM
### Setup
- Click [here](https://code.pyret.org/editor#share=12QOgJeyzUUksWlrGeNfbe95IwYLHBbXT&v=aa9fb79) for the starter code. **To make sure you can save your work, go to the `File` menu and select `Save a copy`, and save the copy as `hw3-code` (don't include `.arr` at the end -- CPO will add this automatically for you when you download the file).**

:::warning
*Note: if you choose to create a new Pyret file from scratch instead of saving a copy of our starter, you will need to change the Pyret context to `dcic2024` as described in the [CS111 Tables documentation](https://hackmd.io/24jQBiHKQsqWBI9Hj8bYnA?view), so that the top of your Pyret file looks like this:**

:::
- Do **not** put your name anywhere in the file.
### Resources
We recommend briefly browsing relevant pages (particularly the CS111 Table documentation, Pyret's String documentation, and the lambda expression documentation) before working on these problems.
- [Pyret documentation](https://www.pyret.org/docs/latest/)
- [Lambda expressions for tables](https://hackmd.io/@cs111/lambdas-tables)
- [CS111 Table documentation](https://hackmd.io/@cs111/table) (use this **instead** of the official `Table` documentation)
- [Strings documentation](https://www.pyret.org/docs/latest/strings.html)
- [Edstem](https://edstem.org/us/courses/84795)
- [Testing, Design, and Style guide](https://hackmd.io/@cs111/pyret-design-clarity-guide)
- Style tip: ALL lines (including comments) must be **under 100 characters long**
## The Assignment
Your friend Jetty McFly is a student at Plane University, and you are helping her navigate through all of the different departments and professors. In order to find the professors you are looking for, you have to create a way to easily look through the large staff at the university.

## Learning Objectives
Our goal this week is to practice several essential skills, including breaking down problems into smaller tasks, using documentation, developing comprehensive collections of tests, and using all of the building blocks we've learned that allow us to compute on Tables. We'll start with problems on a single Table, and then move to problems that use information from two Tables. We're building up to writing more complex programs that process tables as part of doing data analysis (on the first project).
## Part 1: String validation
:::info
Learning Goals:
- To practice writing functions using string functions and boolean operators
- To practice using documentation to find useful built-in functions
:::
**Task 1:** Write a function `in-CIT(office :: String) -> Boolean` that takes in an office, such as `"CIT 429"` or `"Metcalf 322"` and returns a `Boolean` that indicates whether the office is in the CIT, that is, whether it starts with the characters `"CIT "` (not including the quotations, and including the space after the T).
:::spoiler **Hints:**
- For all of the tasks in this part, we suggest starting with a comprehensive set of tests *that take the problem statement literally*. For example, `CIT429`, `CIT`, and `ACIT 4` should return `false`, while `CIT ` should return `true` (because it literally obeys the problem statement). What other examples can you think of?
- Many of the tasks in this section are about which characters are in specific positions in a string. Think about that approach to these problems, and look in the documentation for a `String` function that helps with this.
- Remember that the first position is a `String` is numbered 0, not 1.
:::
::: warning
**Note:** Being able to look in language documentation for useful operations is an important skill, which is why we aren't telling you exactly which `String` operations to use. That said, limit yourself to operations with input and output types that we have used this semester (`Number`, `String`, `Boolean`). Don't use operations that return `List`, as we haven't covered that yet.*
::: spoiler **How to Search for Functions in Documentation**
When trying to use documentation, read over the names and types of the available functions: do any sound relevant? For those that do, look at the text description and the examples for more detail. If you aren't sure whether a function will help, try a small example on your own in the interactions window.
:::
**Task 2:** Write a function called `in-building(office :: String, building :: String) -> Boolean` that indicates whether the office is in that building, that is, whether it starts with the building name followed by a space.
*Hint: how can you generalize the code you wrote in task 1 to this broader task?*
**Task 3:** Write a function called `get-room-number` that takes in a `String` (an office) and returns a `String` of only the office number. For example, `get-room-number("CIT 429")` should return `"429"` (as a `String`). The room number of an office is the part of the String that follows the first space. If the input string does not have a space, it should `raise("Malformed input: no spaces")`. We've seen an example of `raise` in the `get-grade` function in the Sep 15 lecture (take a look at the starter code). [Here](https://www.pyret.org/docs/latest/_global_.html#%28part._~3cglobal~3e_raise%29) is the Pyret documentation.
:::spoiler How do we test if a function raises?
You can use `raises` instead of `is`! See the [Pyret documentation](https://www.pyret.org/docs/latest/testing.html#%28part._testing_raises%29)
:::
## Part 2: Lookup operations
:::info
Learning Goals:
- To give you practice accessing data from tables
- To help you understand the benefit of bundling small pieces of data into one larger piece of data
:::
Take a look at the `FACULTY-DIR` table in your Pyret file (you can see it in full by typing `FACULTY-DIR` in the interactions window), which represents a directory of university faculty. Notice it has the columns "name", "department", and "office".
### Part 2B: Using helper functions on Rows
:::warning
Remember that we have an [explainer on using lambda expressions and Tables](https://hackmd.io/@cs111/lambdas-tables). Be careful of Boolean redundancy!
:::
Copy-paste the following code, which pulls out some Rows from FACULTY-DIR.
```
strong-row = FACULTY-DIR.row-n(0)
pratt-row = FACULTY-DIR.row-n(5)
```
The following tasks are warmups to writing lambda expressions. They're meant to get you to practice writing expressions on specific rows (`strong-row`) and (`pratt-row`) before we move on to the generalized tasks in the next part. You are **not** writing functions or lambda expressions for tasks 4 and 5. Don't overthink these tasks -- the expressions will be very simple.
**Task 4:** Write a single-line expression that uses `in-CIT` to check if `strong-row` has an office that is in the CIT. This expression will evaluate to false. Now, repeat this for `pratt-row`, which should evaluate to true (the only difference between the two expressions should be that `strong-row` gets replaced with `pratt-row`).
**Task 5:** Write a single-line expression that uses `get-room-number` to get the room number of Strong's office from `strong-row`. Run your code and make sure that the output in the right side of the Pyret window has the correct room number.
### Part 3B: Table operations with helper functions
:::danger
*Note: It is **extremely** important that you use the [CS0111 Table documentation](https://hackmd.io/@cs111/table), not the Pyret `Table` documentation. The 111 version includes the documentation for `Row`s, which is necessary for this assignment.*
:::
**Task 6:** Write an expression for computing the table of all of the directory entries of faculty in `FACULTY-DIR` who have offices in the CIT. The result of this expression should be stored with the name `rows-in-CIT` (e.g. you should have something of the form `rows-in-CIT = [some expression to compute the table]` in your code).
:::spoiler Hints on the lambda expression
You will use a lambda expression for this task that generalizes your computation from Task 10. Remember that task 4 had you write expressions for *specific* rows of `FACULTY-DIR`, and now you're writing an expression that generalizes to *any* row in `FACULTY-DIR`. You should be able to make a lambda expression by replacing `strong-row`/`pratt-row` from your expressions in Task 10 with `r` and surrounding the computation with `lam(r):` and `end`. Said otherwise, you're defining an anonymous/nameless function (the lambda) that takes in as input an arbitrary row `r` from `FACULTY-DIR`.
:::
**Task 7:** Some faculty in the directory do not have offices listed. In those cases, the "office" cell of that row is a String of 0 or more spaces (e.g. "" or " "). Write an expression for computing a table of all of the directory entries in `FACULTY-DIR` who do not have an office listed. Your expression should make use of a helper function (one option is for this helper to take in a `String` and return a `String`, but you might have a different approach). Remember to write tests for this helper function. The resulting table should be stored with the name `no-office-fac`.
:::spoiler **Hint**:
The helper function should be used to help determine if a String is only made up of spaces. There are at least two ways to do this using functions in the Pyret String documentation -- by transforming the original `String`, or by generating a new `String` to compare against.
:::
**Task 8:** Write a set of expressions to determine whether all the offices for the Physics faculty (faculty with the department "Physics") are located on the 3rd floor. An office on the third floor has a number with three digits, where the first digit is 3 (for example, "CIT 368" is on the third floor, while "Metcalf 30" is not). Assume all Physics faculty have an office listed in the table. The result of the computation should be a `Boolean` stored with the name `all-physics-third-floor`.
:::spoiler **Hint:**
There are multiple ways how to approach this task. Write down a to-do list of the intermediate computation(s) you might need. Where does it make sense to apply a table operation? Where does it make sense to make a helper function?
:::
## Part 3: Lookup operations and testing
:::info
Learning goals:
* Practice looking up a value in a Table based on information contained in some other column
* Practice writing and testing functions that take in a Table
:::
**Task 9:** Write a function `get-building(fac-name :: String, fac-table :: Table) -> String` that takes in a faculty name and a faculty directory table name and outputs the *building* (such as "CIT") that the faculty is in. Assume all offices are well-formed (that is, unlike in `FACULTY-DIR`, that none are made up of only spaces). Assume a faculty member exists *at most once* in `fac-table`. If the faculty name is not found, the function should `raise("Faculty not found")`. *Note: see task 10 for testing this function. We recommend starting with task 10 and then doing Task 9.*
**Task 10:** From scratch, create a small example `Table` that you will use for testing `get-building`, and write a comprehensive set of tests for Task 9. Remember that your tests should follow the assumptions in the problem statement. For example, because task 9 says that a faculty name exists at most once in the Table, your table should *not* have multiple rows with the same faculty name.
## Part 4: Designing Datasets
:::info
Learning Goals:
- Practice designing and interacting with datasets for different purposes/users
- Think about how table designs and datasets can fail to represent all cases
:::
**Task 11:** The `FACULTY-DIR` Table contained only last/family names of Faculty at an American institution. Let's think about what it would mean to create a table that would store full names of a broader population. Users of the table will add rows to the table with data. [Create a table](https://hackmd.io/@cs111/table#Creating-a-Table-from-Scratch) to store information about names and store 3-5 names within the table. It’s up to you to decide what sorts of column(s) you’ll use for this table.
**Task 12:** Read [this article](https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/). In your code file, copy-paste the following function:
```
fun last-name(name :: String) -> String:
doc: "Returns the last name from the given name"
space-index = string-index-of(name, " ")
string-substring(name, space-index + 1, string-length(name))
where:
last-name("Angus McMoo") is "McMoo"
end
```
based on the article, add 4 different examples in the where-block that would fail on this function, and include a brief comment about why each one fails. **You are not modifying the function, so the tests you write should all show up as failing in the Pyret window.** If the function should produce an error for some name, you can indicate that with a raises. For example,`last-name(“Cher”) raises “No last name!” # Cher does not have a last name`
**Task 13:** In a block comment under the `last-name` function, answer the following:
- Identify any assumptions that the structure of your table (i.e. your choice of columns) does not account for. Provide two example names that would not fit into your table.
- Explain one modification you would make to the structure of your table to allow for more names to be stored in the table. Would it affect how current names are stored? What are the downsides of this new choice?
**Task 14:** While the design of a dataset embodies certain assumptions, no dataset can be perfectly representative due to limitations with data collection and data storage. Consider the following groups who are interested in using a name dataset.
- WTube is a video sharing platform currently designing a version of their platform targeted toward kids, called WTubeKids. They would like to use the name table to display names in comments.
- MailApe is an email marketing company. They would like to use the name table to send personalized emails to customers.
- AnalyticsAnalysis is a data analytics research group that is keeping track of how frequently celebrities are mentioned on social media. They would like to use the name table to store the names of celebrities they are tracking.
In a block comment, answer the following questions for each of the groups:
- What information does the group need from a user to accomplish their task? Think columns in a table, such as full name, first name, last name, preferred name... what else?)
- Are there any relevant assumptions in play? Based on how the data is being used, is there anything important to allow / disallow? Who is included in the dataset, and who would be excluded?
## Part 5: Working with multiple Tables
:::info
Learning Goals:
- Practice planning programs
- Combine data across two tables to answer a question
- Write and test a function that merges two Tables
:::
In these tasks, along with `FACULTY-DIR`, you will use the `TRAVEL` Table. This gives the travel times, in minutes, to get between different buildings. Take a look at the `TRAVEL` Table now.
**Task 15:** Write a function `get-time(fac1 :: String, fac2 :: String, fac-table :: Table, time-table :: Table) -> Number` that takes in two faculty names and two tables (the first one that looks like `FACULTY-DIR` and the second one that looks like `TRAVEL`) and provides the time it takes to travel between their offices. Some notes:
* Assume that travel time is symmetrical (the time it takes to travel from CIT to Kassar is the same as the time it takes to travel from Kassar to CIT)
* Assume that both faculty have a valid office listed in `fac-table`
* If two faculty are in the same building, the travel time should be 0
* If two faculty are not in the same building, assume that there is a row that lists either the travel time between the first office and the second office or vice versa (but not both) in `time-table`
* For testing this function, you can just use `FACULTY-DIR` and `TRAVEL` as your input Tables
* Remember that you did some work in task 9 that might help here. What else do you need to accomplish this task? Write out a plan!
**Task 16:** Write a function `from-dorm(fac-table :: Table, time-table :: Table) -> Table` that: 1) discards all rows from the `fac-table` where the office is only made up of spaces and 2) adds a column called `"from-Andrews"` that contains the time to travel from Andrews to that faculty member's building. Assume that `time-table` has travel times to get between Andrews and every building in `fac-table`. See Task 17 for testing this function. **Again, create a plan for this task before starting!**
**Task 17:** Create *one* test input faculty Table for `from-dorm`. By hand, also create the output that you expect when `from-dorm` is called with this table (and `TRAVEL` as the second input). Your where-block for `from-dorm` only needs to include one example, that uses these Tables.
## Check Block (Autograder Compatibility)
When you complete all the tasks of this homework, please copy the following `check` block into the bottom of your code file!
The `check` block will be checking that all required functions and names are included, correctly named, and that they handle inputs in the right order. This is the bare minimum for the autograder to function properly -- do not edit this!
```
check "functions exist and have correct inputs":
in-CIT("") is false
in-building("", "") is false
is-string(get-room-number("CIT 333")) is true
is-table(rows-in-CIT) is true
is-table(no-office-fac) is true
is-boolean(all-physics-third-floor) is true
is-string(get-building("Strong", FACULTY-DIR)) is true
is-number(get-time("Strong", "Strong", FACULTY-DIR, TRAVEL)) is true
is-table(from-dorm(FACULTY-DIR, TRAVEL)) is true
end
```
If you see this block appear in the interactions window after running it, then you are fine! Please submit to Gradescope.

If not, double-check your function names, input types, and input order. If you are still stuck, please feel free to come to hours or post on Ed!
## Handin
- Download your code as `hw3-code.arr` Hand in your work on [Gradescope](https://www.gradescope.com/courses/1103553) in the assignment named "Homework 3"
## Theme Song
[Airplanes](https://open.spotify.com/track/6lV2MSQmRIkycDScNtrBXO?si=9684274185de4e3f) by B.o.B. featuring Hayley Williams
## Spotify Playlist
<iframe style="border-radius:12px" src="https://open.spotify.com/embed/playlist/6HiBE5A4YvHZHC5jwxZYoe?utm_source=generator" width="100%" height="352" frameBorder="0" allowfullscreen="" allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy"></iframe>
------
> Brown University CSCI 0111 (Fall 2025)
> Images from pixabay.com
<iframe src="https://forms.gle/avVrN7H8u6hjiH8j7" width="640" height="372" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>