Assignment 2: Ads Take Aim

Assigned Thursday, 1 February
Due Wednesday, 7 February, 11:59 p.m.
Joe Dator, The New Yorker, 21 July 2014

Targeted advertising is a real-world example of how data, computation, and social impacts come together. With this assignment, we want you to develop a basic understanding of how these systems work.


Assignment guidelines

  • Create a new file named asmt02.arr on (CPO). Do not put your name in your assignment or the filename; we want to grade anonymously.

  • As always, your friendly coaches and professor are here to help with this assignment! Check coaching hours and your professor’s office hours.

Introduction: Representing ads

Winifred is the owner of a sporting goods store in Poughkeepsie. Recently she’s seen advertisements for a competitor all over town. Afraid of losing business, Winifred hires the Vassar Bros. Ad Agency for help.

The first step in processing something with a program is to represent that thing in terms of focused, discrete pieces of data. For this assignment, we will use three pieces of information to represent an ad:

  • the age of person it targets,
  • the location of the event, and
  • the kinds of activities it involves.

We’ll start by thinking about the simplest form of matching ads: writing explicit conditional expressions to see whether a person is in the target audience for a single, fixed ad. Therefore, we can store the information about the ad in three constants:

TARGET-TOWN = "Poughkeepsie"
TARGET-HOBBIES = "running, biking, walking, swimming"

Task: Copy and paste these definitions into the top of your code.

Part 1: Targeted ads

Next, let’s help the ad agency figure out what customers are good matches for Winifred’s ad. To decide if someone is a good potential customer for Winifred to advertise to, we’ll write a series of predicates – functions that return the Boolean values true or false. Make sure to write examples for each function before you try writing the function body.

Exercise 1: Age

Let’s start by writing a function to see if any potential customer is within five years of the ad’s target age.

4 points

Task: Define the function

fun within-five(age :: Number) -> Boolean:

It should return true if the input, age, is within five years of TARGET-AGE and false if not. You may want to refer to the Number documentation.

This should be an inclusive comparison, meaning that if the target age is exactly five years older or younger than the target, the function should return true.

Exercise 2: Interest

Since Winifred is looking for a variety of interests that customers might have, we want to see if a customer’s interest is one of her target hobbies for the ad.

4 points

Task: Define the function

fun hobby-relates(hobby :: String) -> Boolean:

It should return true when the input hobby is contained in TARGET-HOBBIES (that is, it’s a substring) and false otherwise. You may want to refer to the String documentation.

Exercise 3: Location

Winifred also wants to match a person to the ad based on their location, since they need to be able to get to her store. However, TARGET-TOWN only gives us a specific place! To solve this issue, we need to write a function to check if a certain location is in the target town or its surrounding area:

4 points

Task: Define the function

fun is-nearby(town :: String) -> Boolean:

It should return true if the input is "Hyde Park", "Pleasant Valley", "Poughkeepsie", or "LaGrange", and false otherwise.

Hint: The input "Park" should return false even though "Hyde Park" is one of the towns. Consider: Why is this the case? What makes this different from the task above where we check if TARGET-HOBBIES contains a particular hobby?

Now we can find out if someone lives in the area, but Winifred knows that people can only get to her store if they live in the target town itself (so they can walk) or if they can drive to the target town from another town in the area.

Solving this problem gives us a chance to practice using functions to write other functions.

4 points

Task: Define the function

fun in-range(town :: String, has-car :: Boolean) -> Boolean:

The inputs represent a customer’s town and whether they have a car or not. The function should return true

  • if the input town is TARGET-TOWN or
  • if the input town is nearby and the person also has a car.

Otherwise, the function should return false.

Do not repeat the code you already wrote in is-nearby!

Exercise 4: Combining criteria (coach-free)

Now it’s time to put all the criteria together to determine whether the ad should be shown to a potential customer or not!

4 points

Task: Define the function

fun show-ad(age :: Number, town :: String,
    hobby :: String, has-car :: Boolean)
  -> Boolean:

The inputs are information about a potential customer, and the output is true when

  • their age is within five years of the target age (inclusive),
  • their town is the TARGET-TOWN or they have a car and their town is nearby, and
  • their hobby is contained in TARGET-HOBBIES.

Otherwise, the output is false.

Hint: Consider previous tasks you have completed! Make sure to avoid redundant code or functions that do the same thing!

Part 2: Pyret style and testing check

Remember that programs aren’t just written for computers to run; they’re also for people to read. Just as there is good style for writing an English essay, there is good style for writing a program.

Starting with this assignment, you will be graded on following good Pyret style and having examples that cover a variety of situations. Read the Testing and Style Guidelines for details.

6 points

Task: Take a moment to go back through the functions you’ve written:

  • Did you write a docstring for each function?
  • Do you have examples that demonstrate the functions work as intended?

If not, do so now!

Do any of your functions look like this?

if some-question:

This is very common, especially if you’ve used other programming languages before. However, the ifelse is redundant; you could just write some-question and get the same result!

Task: Remove any redundant if expressions!

Part 3: Differences and limitations (coach-free)

Let’s think a bit about the approach we just implemented for matching ads to people.

6 points

Task: Respond to the following questions:

  • How do you think these functions differ from how real ads are targeted?
  • Think about the way we set up the code and the programming operations that we used:
    • What are the limitations of our current code/operations for evaluating ads?
    • What would you want to be able to do in code to do a better job of targeting ads?

You can put your answers in a multi-line comment

2 points

Task: In a check block (just like a where block but not attached to any particular function), write two examples using show-ad, demonstrating a situation in which the function would output false (because of a limitation of the function), even though the ad would otherwise seem a good match for the person.

A check block is like a where, except it’s not attached to the definition of a particular function. For example,

  show-ad(...) is false

Part 4: Personal data and privacy (coach-free)

Beyond teaching you technical skills around computing and data, CMPU 101 also wants to help you think about the broader societal issues surrounding them.

Task: Read the article “These Ads Think They Know You” on the kinds of information that advertisers are able to access and use when targeting ads to users. You have free access to the New York Times as a Vassar student. Follow these directions to set up your account!

Task: Answer the following prompts using your own Google ad-matching information or – to protect your privacy – the sample shown below. Your answers can go in a multiline comment at the bottom of your program.

Google ad center
  1. Information that a search engine has on you comes from a combination of

    • your profile and
    • assumptions that the search engine makes about you based on your browing history, users that are similar to you, etc.

    3 points Identify three pieces of information that are inferred about you by Google and two ways that Google inferred that information. Your answer should look like “X likely comes from a search I made and Y piece of information. Z likely comes from A and B.”

  2. 4 points Pick two pieces of ad-matching information, which can be the same or different from what you used in the last question. For each, describe

    • one possible use which is beneficial or benign, and
    • one which you believe is problematic, unethical, or harmful.

    Your answer could look like “Google knows I like hybrid alternative vehicles; one benefit is X and one harm is Y.”

    Reference at least two of the following criteria somewhere in your response:

    • Intent/purpose (academic research vs targeted ads)
    • If the data is public, does that mean it can be used in any way?
    • Timing (e.g., data set from a decade ago)
    • Attributes collected (e.g., those protected by law from discrimination such as religion, race, age, or disability)
    • Inference potential: What might this information help companies infer about you?

    There’s no right or wrong answer here. Our goal is to get you thinking about the context of the technical content of the course. Your answer should be clear and concise, with enough specifics to show that you are thinking about the question beyond a surface level.

Challenge exercise (coach-free)

In reality, ad-matching systems check dozens of pieces of information about users, not just four like show-ad did. Does that mean real ad systems have functions with 40–50 parameters? No!

Instead, real ad systems bundle multiple pieces of information about a user together to make it easier to handle. For example, the information about one user could be a row in a larger table of potential customers. When you’re working with tables, refer to the CMPU 101 Table documentation rather than the Pyret documentation.

Our goal is to update the show-ad function to work with individual rows, rather than separate pieces of information. Specifically, we want the inputs of show-ad2 to look like:

fun show-ad2(user-info :: Row) -> Boolean:

where the user-info is a row from a table of user data which has columns for age, town, hobby, and has-car.

Task: Since you’ll be working with tables, at the top of your file, add the line

include shared-gdrive("dcic-2021",

Task: Copy this table definition into your program:

  table: age, town, hobby, has-car
    row: 21, "Poughkeepsie", "swimming", false
    row: 29, "LaGrange", "swimming", true
    row: 25, "Hyde Park", "swimming", false
    row: 27, "Beacon", "swimming", true
    row: 93, "Poughkeepsie", "swimming", true
    row: 20, "Poughkeepsie", "reading", true
3 points

Task: Using these constants and helpers, write show-ad2 that takes a user Row and returns a Boolean. This new version of show-ad should extract needed data about the user from the given Row.

As a reminder, show-ad2 returns true when the customer’s age is within 5 of TARGET-AGE, the customer lives in TARGET-TOWN itself or within the surrounding area and has a car, and TARGET-HOBBIES contains the customer’s favorite hobby. The output is false otherwise.

Be sure to write tests for show-ad2 in its where block.

Note: Figure out how to use the previous functions that you’ve written as helpers for this problem. You only need to write a bit of additional code for this problem. Think about how to break the problem down in a way that you can reuse the functions you’ve already written.

Check block (autograder compatibility)

Task: Copy the following check block into the bottom of your program:

check "Functions exist and have correct inputs":
  in-range("", true)
  show-ad(0, "", "", true)

This check block ensures that you’ve included all the required functions, named correctly, and that they handle inputs in the right order.

If you did the challenge exercise, you can add these lines to the check block:

  t1 =
    table: age, town, hobby, has-car
      row: 0, "", "", false

If you see this block appear in the interactions window after running it, then you are fine:

Check passed

Instead, if you see one of these screens, please check your function names, input types, and input order:

Check failed Check failed

Submitting the assignment

  1. Download your file (FileDownload) and ensure it’s named asmt02.arr.
  2. Upload your assignment on Gradescope.

Most of the functions (in Part 1 and the challenge exercise) will be automatically graded when you submit your assignment, but your final assignment grade will be determined by your instructor when they review your work, including checking the programming style and tests (Part 2) and reading your answers for Part 3 and Part 4.

Note: You can submit as many times as you want before the deadline. Only your latest submission will be graded.