Assignment 3 — Lists

One question, asked of a whole list. First with the built-in list functions, then by writing one yourself, then about people rather than stripes.

Due Sep 15, 2026

This assignment comes in three parts, and they unlock on different days.

There is a class between this going out and the deadline, unlike last week. Bring what is broken to it.

AI: the course AI policy applies in full. No AI-generated code, and no asking a chatbot to solve these problems before the deadline. The optional problems say when that changes.

Starting code

Copy this into a fresh Pyret file called a3-lists.arr.

import lists as L

unit = 20

fun stripe(u, color):
  if u < 10:
    rectangle(u * 6, u, "solid", color)
  else:
    rectangle(u * 6, u, "outline", color)
  end
end

That first line is not optional and not decoration. L.map, L.filter and L.fold live in a library that is not loaded until you ask for it, and without that line every problem below fails with an error that does not mention the import. If you see L is unbound, this is why.

stripe is the two-branch version from A2. If yours grew an else if or a formal parameter, use the simple one above for this assignment — the lists are the new thing here, and a three-branch stripe makes the examples harder to write without teaching you anything extra.

The reading is [DCIC] 5.1 — From Tables to Lists and [DCIC] 5.2 — Processing Lists.

Part A — one question, asked of a whole list

  1. Make a flag from a list of colors. Write a list of at least four color strings, use L.map to turn it into a list of stripes at unit, and L.fold to stack them into one picture. This is Wednesday’s class again, from a blank file.

    colors = [list: "red", "white", "red", "white"]
    stripes = L.map(lam(c): stripe(unit, c) end, colors)
    L.fold(above, empty-image, stripes)

    Then pull one stripe out of the list with .get and look at it on its own:

    stripes.get(0)

    That is [DCIC] 5.1 — From Tables to Lists §5.1.4.4, and it is the only way you have of getting at a single element so far.

    • L.fold is the one thing here that nobody has explained. You handed it above and it worked. Problem 4 is where you write that walk yourself, and after it L.fold stops being magic.
    • Your stripes come out see-through, because stripe outlines anything from 10 up and unit is 20. Change unit to 9 if you want them filled in.
  2. Write outlined. It takes a list of numbers and gives back the ones stripe would draw as an outline rather than solid.

    fun outlined(units :: List<Number>) -> List<Number>:
      doc: "the units that stripe draws as an outline rather than solid"
      ...
    where:
      ...
    end
    • Four examples, written before the body. One of them contains 10, and one of them is the empty list [list: ].
    • We started this in class on Wednesday. If yours works, this problem is already done and you should say so in a comment rather than rewriting it.
    • The body is one line. The where: block is what this problem is worth, and it is graded that way.
  3. Both at once. Write outline-widths, which takes a list of units and gives back the widths of just the ones that get outlined. So outline-widths([list: 4, 10, 20]) is [list: 60, 120], because 4 is dropped and a stripe’s width is u * 6.

    • Use L.filter and L.map together. Do not write it as one pass.
    • Three examples, one of them a list where nothing survives the filter.

Part B — write one yourself (after Monday)

  1. Count them by hand. Write count-outlined, which takes a list of units and returns how many of them would be outlined.

    fun count-outlined(units :: List<Number>) -> Number:
      doc: "how many of these units stripe draws as an outline"
      ...
    where:
      ...
    end
    • No library function that walks the list for you — not L.filter, L.length, L.map, L.fold, L.sum, or anything else you find in the docs that does the walking. Use cases, the way we do on Monday. The whole point is to do by hand what problem 2 and L.fold had done for you.
    • Start from the empty list. Write that example first and write the answer down before you write any code.
    • stripe is if u < 10. Work out what that does at exactly 10 before you write the body, and put a 10 in one of your examples.
    • This is [DCIC] 5.2 — Processing Lists §5.2.3, which does exactly this shape on a different problem.
If you get stuck on problem 4, submit the examples

A where: block with correct examples and a body you could not finish is worth most of this problem. An empty problem is worth nothing. Write the examples Monday night whatever else happens.

Part C — the same idea, about people

The two problems above ask one question of every number in a list. This one asks one question of every person, which is the same code and not the same thing.

  1. Write show-ad. This is [DCIC] 3.4 — Conditionals and Booleans §3.4.4’s own exercise. It takes an age and a hair color and returns true if the person is between 9 and 18 and has either pink or purple hair. “Between 9 and 18” includes both of them — a nine-year-old is shown the ad, and so is an eighteen-year-old.

    • Write it twice: once with if expressions, and once using only and, or and comparisons, with no if at all. Keep both, and name them show-ad-if and show-ad-bool.
    • Say where the edges are in the doc: line, and make both versions agree with what it says.
    • Give each of them four examples. At least one example must be a person the two versions had better agree about at a boundary — age 9 or age 18.
  2. Ask it of everyone. Here is a list of the ages of people who visited the site this morning:

    visitors = [list: 8, 9, 14, 17, 18, 19, 23, 41, 67]

    Use L.filter to produce the ages your ad would be shown to, ignoring hair color. One line.

  3. Then answer this in a comment, in three or four sentences. It is graded, and it is the only part of this assignment with no right answer.

    Your program divided nine people into two groups. Name one person it says no to who you think should have seen the ad, and one it says yes to who should not have. Then: what did the program assume about the connection between someone’s hair color and what they want to buy? Who wrote that assumption down?

    The book’s own callout on this is in [DCIC] 3.4 — Conditionals and Booleans §3.4.4, and it opens “Assumptions about users get encoded in even the simplest functions.” It is worth reading before you answer, and it links a ProPublica investigation into a program that sorted people into two groups with rather more at stake than an advertisement.

  4. Submit a3-lists.arr on Brightspace. One file, and make sure it runs from top to bottom before you send it.

Grading

Full credit for a file that runs and does 1 through 7.

Most of the weight is on three things:

  • The where: blocks, in problems 2 and 4 — the empty list present, the boundary present, and the answers worked out rather than copied from the body.
  • The base case, in problem 4. A cases expression whose empty branch is wrong or missing is the one mistake that matters this week.
  • Problem 7. Three honest sentences beat a paragraph that agrees with the question.

Presentation

Two of you will be asked on Wednesday, September 16 to put your file on the projector and walk the class through it. You will not be told in advance.

One of the two will be asked about problem 7 rather than about code. Be ready to say what you think, not what you think is expected.

What else to do (optional part)

Ungraded. No points, and skipping them costs nothing.

  1. Write count-outlined a second way, using L.filter and L.length in one line. Put it next to your cases version. Which one would you rather read in six months, and which one taught you more to write?

  2. Write L.fold yourself, for pictures. Write all-beside, which takes a list of images and puts them side by side as one image, using cases. Then check it against L.fold(beside, empty-image, ...) on the same list. Two questions worth more than the code: what should it give back for [list: ], and is there more than one defensible answer?

  3. [Harder, and genuinely optional] L.fold has a mirror image called L.foldr, which walks the list from the other end. On your flag the two draw the same picture. Find a list and a function where they do not, and say in a comment which one problem 1 needed. You would have to work this out from the documentation; try it only if problem 4 felt easy.

  4. Change show-ad so it also refuses anyone whose age is missing — decide yourself what “missing” looks like in a list of numbers, and say why you chose that. This is a harder question than it sounds and it is the reason [DCIC] 5.2 — Processing Lists spends a whole section on lists with awkward members.

  5. [Consulting AI allowed, after the deadline only] Ask a chatbot to write count-outlined for you and see whether it uses cases or reaches for a library function. Then ask it what happens on the empty list. Say in a comment whether it was right, and whether you could tell without running it.