Lab 7: Call the Plumber (a.k.a. A Tree By Any Other Name)
Learning objectives
The purpose of this lab is to:
- give you practice modeling phenomena in our world using Trees
- give you practice working with structurally recursive data definitions
- give you practice writing functions using a template for structurally recursive data definitions
Setup
Create the file lab07.arr
and copy/paste the following header comment into it:
#|
CMPU-101
Fall 2021
Lab 7
Name: your name
|#
As usual, ask your instructor or a coach if you're stuck. Remember to save your work every so often.
Description
We would like to represent pipelines in our program. A pipeline has faucets (opened or closed):
faucet open | faucet closed |
---|---|
straight parts (copper or lead):
one straight pipe leading to a faucet | two straight pipes leading to a faucet |
---|---|
and branches. Here are two pipelines with branches:
pipeline with one branch | pipeline with several branches |
---|---|
Data Definition
We can represent pipelines as described above with the appropriate data definition. Since our pipelines consist of multiple instances of faucets, straight pipes, and branches, our data definition includes these three varieties. Copy this data definition and examples of pipelines into your ''lab07.arr'' file:
data Pipeline:
| faucet(open :: Boolean)
| straight(kind :: String, pl :: Pipeline)
| branch(pl1 :: Pipeline, pl2 :: Pipeline)
end
# Examples of pipelines
f-closed = faucet(false)
f-open = faucet(true)
straight-cop = straight("copper", f-closed)
straight-cop-lead =
straight("copper",
straight("lead", f-closed))
branching-pipeline =
branch(
branch(
straight("copper", f-open),
f-closed),
branch(
f-closed,
f-closed))
Template
Since we defined a new type of data (Pipeline), we need to create a new Template for functions that take a Pipeline as input. Copy this template into your ''lab07.arr'' file:
#|
fun pipeline-fun(pl :: Pipeline) -> ...:
doc: "template for a function that takes a pipeline"
cases (Pipeline) pl:
| faucet(open) =>
... open ...
| straight(kind, pl1) =>
... kind ...
... pipeline-fun(pl1) ...
| branch(pl1, pl2) =>
... pipeline-fun(pl1) ...
... pipeline-fun(pl2) ...
end
where:
pipeline-fun(...) is ...
end
|#
# Exercise 1
# Exercise 2
# Exercise 3
# Exercise 4
# Exercise 5
Exercise 1
Implement the function, ''is-water-running'', which takes a pipeline and determines whether any faucets are open.
To help you get started, here's our solution. Copy/paste it into your ''lab07.rkt'' file. Study it, run it, and make sure you understand how it works. Then go on to the next exercise.
# Exercise 1
fun is-water-running(pl :: Pipeline) -> Boolean:
doc: "determines whether any faucets are open in pl"
cases (Pipeline) pl:
| faucet(open) =>
open
| straight(kind, pl1) =>
is-water-running(pl1)
| branch(pl1, pl2) =>
is-water-running(pl1) or is-water-running(pl2)
end
where:
is-water-running(f-open) is true
is-water-running(f-closed) is false
is-water-running(straight-cop) is false
is-water-running(straight-cop-lead) is false
is-water-running(branching-pipeline) is true
end
Exercise 2
Implement the function, ''count-faucets'', which takes a pipeline and counts the number of faucets.
Exercise 3
Implement the function, ''count-open'', which takes a pipeline and counts the number of open faucets.
Exercise 4
Implement the function, ''modernize'', which takes a pipeline and converts all "lead" straight pipes to "copper"
Exercise 5
Implement the function, ''off'', which takes a pipeline and turns off all the faucets