Assignment 2: Ads Take Aim

Assigned: Thursday, 8 September
Due: Wednesday, 14 September, 11:59 p.m.

Targeted advertising cartoon

Joe Dator, The New Yorker, 21 July 2014

  • Create a new file named asmt02.arr on Pyret.

  • Do not put your name in your assignment; we want to grade anonymously.

  • 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.

  • Try to write your tests before filling in your functions, so you can quickly tell if they are working correctly.

The Pyret documentation is accessible from the pirate button in the top left corner of code.pyret.org.

Your friendly coaches and professor are here to help with this assignment! Check coaching hours and my office hours.

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 agency recommends targeting people living nearby who would be able to get to a store in downtown Poughkeepsie. They decide specifically to target people with sporting interests in their twenties. The ad agency already has data on locals’ age, hobbies, town, and whether they have a car.

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

TARGET-AGE = 25
TARGET-TOWN = "poughkeepsie"
TARGET-HOBBIES = "running, biking, walking, swimming"

These definitions are for global variables, which are variables (names) created outside of a function, which are accessible to all functions throughout the program. They are normally defined in the top of the program and are distinguished from local variables by having upper-case names.

Next, let’s help the ad agency figure out what customers fit Winifred’s criteria. We want to write a function that takes a person’s age, hobby, town, and car status and determines whether or not Winifred should send them an ad.

To do this, we first need to figure out more information about them.

To decide if someone is a good potential customer 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.

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

    Task: Define the function

    fun within-5(age :: Number) -> Boolean:
      ...
    end
    

    It should return true if the input, age, is within five years of TARGET-AGE and false if not.

    (Check out 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.

  2. 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.

    Task: Define the function

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

    It should return true when the input hobby is contained in TARGET-HOBBIES and false otherwise.

    (Check out the String documentation!)

  3. Winifred wants to be able to see if a person’s town is within the general area of 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.

    Task: Define the function

    fun in-area(town :: String) -> Boolean:
      ...
    end
    

    It should return true if the input is "hyde park", "pleasant valley", "poughkeepsie", or "lagrange" (the towns around her store), 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 global variable TARGET-HOBBIES contains a particular hobby?

  4. 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 or if they can drive to the target town from another town in the area.

    Task: Define the function

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

    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 in the target area and the person also has a car. Otherwise, the function should return false.

    Hint: Can you reuse any of the functions that we already wrote?

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

Task: Define the function

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

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 within the target area, 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!

A different way of targeting ads is looking at keywords in the text of the advertisement rather than specific criteria like Winifred’s target definitions.

Task: Define the function

fun show-ad2(ad :: String, age :: Number) -> Boolean:
  ...
end

The input ad is the text of an ad and age is a person’s age. The function should return true if any of the following conditions are met:

  • The customer’s age is 35 or younger and the ad contains the word “active”,
  • The customer’s age is 65 or older and the ad contains the word “healthy”, or
  • The ad contains the word “sport”.

Otherwise, it should return false.

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.

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:
  true
else:
  false
end

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!

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

check "Functions exist and have correct inputs":
  within-5(0)
  hobby-relates("")
  in-area("")
  in-range("", true)
  show-ad(0, "", "", true)
  show-ad2("", 0)
end

A check block is similar to a where block, but not attached to an individual function. 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 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

Let’s think a bit about the two approaches we’ve implemented for matching ads to people, show-ad and show-ad2.

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

#|
  Like
  this
  one!
|#

at the bottom of your program.

Task: In another multiline comment, write at least two test examples that demonstrate weaknesses of show-ad and at least two test examples that demonstrate weaknesses of show-ad2.

The output from each function for each input should be surprising given the input. That is, an ad could seem perfect for the customer, but the function would output false because of a limitation of its design or vice versa. Remember that ad-text could be a String containing multiple words!

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 (from a real person). Your answers can go in a multiline comment at the bottom of your program.

How your ads are personalized

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

    • your profile,
    • your browsing history, and
    • assumptions that the search engine makes about you based on your browing history.

    Identify one piece of ad-matching information of each type. Your answer should look like “X likely comes from the profile, Y likely comes from browsing history, etc.”

  2. Pick one piece of ad-matching information that could have come from multiple sources. Give 2–3 concrete examples of online activities (e.g., “searched for X”) that might have associated that ad-matching label with the account.

  3. 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.

    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.

This part is entirely optional and will not be graded, but you may find it rewarding to try!

When we use a search engine, ads related to those searches sometimes appear in the same window. That suggests that the content of our search terms (also known as “queries”) might be used to select ads. For this problem, you will work with a simple version of this setup.

Assume that an ad is an arbitrary String and that a query can have up to three words (such as “bike”, “store”, “vassar”). We want to rate an ad for how well it fits these three words. We will score each word against the ad. A word contributes a score of 1 if it (or a simple modification to it) appears in the ad; otherwise it contributes 0. The rating for an ad against the whole query is the sum of the ratings for each of the three query words divided by the length of the ad String (in characters).

For this question, we will consider modifications that make a word singular (by removing an “s” from the end, e.g., "helmets""helmet") or turn a gerund into a verb (by removing “ing” from the end, e.g., "skateboarding""skateboard"). This means that any of the query words can score against an ad with or without an ending removed.

Task: Complete the following function:

fun rating(ad :: String,
    wd1 :: String, wd2 :: String, wd3 :: String) -> Number:
  ...
end

Your work should emphasize two skills:

  • How to structure your code. The computation itself is less important than how you organize your code (using named computations, helper functions, etc.).
  • A set of good examples for any functions you write for this problem.

This question doesn’t earn any points. It is meant to let you fine-tune your skills at structuring code and developing good sets of examples to illustrate a problem.

  1. Download your file (FileDownload) and ensure it’s named asmt02.arr.

  2. Upload your assignment on Gradescope.

Part 1 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 (Part 2) and reading your answers for Part 3 and Part 4.

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

This assignment is adapted from Kathi Fisler and colleagues at Brown University.