# Assignment 2: Ads Take Aim

 Assigned Thursday, 1 February Due Wednesday, 7 February, 11:59 p.m.

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 code.pyret.org (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.

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-AGE = 25
TARGET-TOWN = "Poughkeepsie"
TARGET-HOBBIES = "running, biking, walking, swimming"
```

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

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

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

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

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

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

```fun is-nearby(town :: String) -> Boolean:
...
end
```

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

```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 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

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

This is very common, especially if you’ve used other programming languages before. However, the `if``else` 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?

```#|
Like
this
one!
|#
```
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,

```check:
...
end
```

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

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

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

• 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:
...
end
```

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

```include shared-gdrive("dcic-2021",
"1wyQZj_L0qqV9Ekgr9au6RX2iqt2Ga8Ep")
```

```CUSTOMERS =
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
end
```
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.

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

```check "Functions exist and have correct inputs":
within-five(0)
hobby-relates("")
is-nearby("")
in-range("", true)
end
```

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
end
```

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

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

## Submitting the assignment

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