# Assignment 2: Thinking Algorithmically

- Due
- Tuesday, 5 September 2017 by 10:30pm
- Summary
- For this assignment, you will identify the parts of an algorithm, find some problems with that algorithm, and write an improved version. You will then design some of your own algorithms in Scheme.
- Purposes
- The purpose of this assignment is for you to practice identifying the parts
of algorithms, to get some experience thinking carefully about
the
*edge cases*where an algorithm could go wrong, and to get you started thinking in Scheme. - Collaboration
- You must work with your assigned partner(s) on this assignment. You may discuss this assignment with anyone, provided you credit such discussions when you submit the assignment.
- Submitting
- Email your answer to csc151-01-grader@grinnell.edu. The subject of your email should be
**[CSC151 01] Assignment 2**and should contain your answers to all parts of the assignment. Scheme code should be in the body of the message, not in an attachment. - Warning
- So that this assignment is a learning experience for everyone, we may spend class time publicly critiquing your work.

## Problem 1: A Birthday Problem

*Topics:* algorithms, parts of algorithms, testing

In any sufficiently large group of people, the likehood that at least two people were born on the same day of the year is surprisingly high (over 50% for a group of 23 people, source: Wikipedia). While this is an interesting theoretical result, it would be nice to test it in class. The following algorithm is *supposed* to tell us how many students share a birthday with at least one other student in class, but it has some problems:

- All the students in the class line up in an arbitrary order.
- The instructor erases the whiteboard.
- We will call the student at the front of the line
*student A*. - We will call the student next in line
*student B*. - Student B announces their birthday while student A listens.
- Student A compares their own birthday to student B’s birthday.
- If both birthdays are on the same day of the year, skip to step 11. If not, continue to step 8.
- If student B is at the end of the line, go to step 14. Otherwise, continue to step 9.
- The name “student B” will now refer to the next student in line behind our current student B.
- Go to step 5.
- The instructor writes one tally on the whiteboard.
- Both students A and B exit the classroom.
- If there is at least one student left in line, go to step 3. Otherwise, continue to step 14.
- the number of tallies on the whiteboard is the number of students who share a birthday with at least one other student. Exit the algorithm

### Part A: Understanding the birthday algorithm

Explain, in your own words, the high-level idea behind this algorithm. Ambiguity is okay: the goal of this part is to guess the *intent* of the algorithm designer, not the exact steps. If you believe the intent does not match the actual steps, try to summarize what you believe the algorithm designer meant to do.

### Part B: Parts of the birthday algorithm

The algorithm above uses all six of the parts of an algorithm covered in the Algorithms reading. Find an example of each piece of an algorithm and list the step(s) that demonstrate that algorithmic building block. Briefly explain your choice.

i. Identify an example of *sequencing* in the algorithm above. Identify the step(s) that demonstrate this algorithmic building block, and explain your choice.

ii. Identify an example of *repetition* in the algorithm above. Identify the step(s) that demonstrate this algorithmic building block, and explain your choice.

iii. Identify an example of a *conditional* in the algorithm above. Identify the step(s) that demonstrate this algorithmic building block, and explain your choice.

iv Identify an example of a *variable* in the algorithm above. Identify the step(s) that demonstrate this algorithmic building block, and explain your choice.

v. Identify an example of a *parameter* in the algorithm above. Identify the step(s) that demonstrate this algorithmic building block, and explain your choice.

vi. Identify an example of a *subroutine* in the algorithm above. Identify the step(s) that demonstrate this algorithmic building block, and explain your choice.

vii. Identify the *inputs* to and *outputs* from the algorithm above.

### Part C: Problems with the birthday algorithm

The birthday algorithm provided with this assignment has some problems. Find two problems with the algorithm and explain them below. At least one of the problems you identify should relate to the correctness of the algorithm rather than issues with clarity, efficiency, or precision. When you describe a problem with the algorithm that will cause it to produce an incorrect result, provide an example situation where you would get the wrong answer.

### Part D: Repairing the birthday algorithm

Write a new birthday algorithm that will produce the right answer. Make sure to address the issues you identified in part C. You should use an approach roughly equivalent to what you summarized in part A.

## Problem 2: Mad Libs

*Topics:* Scheme basics, Strings

Mad Libs is a popular word game in which one player selects a secret story *template* with several unspecified words. The missing words are ordered and may be a variety of types (e.g. nouns, verbs, adjectives). After the player secretly selects a story template, they prompt the other players for the missing words, and then proceed to read the story out loud with the words inserted into the blanks. The results can be quite entertaining!

In this problem you will implement a simple program to automate filling in the choice of words into a simple Mad Libs template. First, create the following six definitions.

```
(define noun ...)
(define noun-plural ...)
(define pronoun ...)
(define adjective-1 ...)
(define adjective-2 ...)
(define verb ...)
```

These definitions will be the “unspecified words” and will be used in our story template. Be sure to replace the “…” in each of the definitions above with actual words (e.g. “house” for noun).

i. Define the string `story`

that contains the following text with the above definitions substituted into the text.

CSC 151 is a ADJECTIVE-1 class! The professor has us VERB all day long. I also have met many ADJECTIVE-2 NOUN-PLURAL in the class. I definitely would recommend the class to PRONOUN.

ii. Add the line `(display story)`

to your file and try running your program on a variety of inputs to see what the resulting story is in each case.

## Problem 3: Scoring divers, gymnasts, and similar athletes

*Topics:* Scheme basics, Numeric computation, Simple lists

As you may know, in many sports, such as diving and gymnastics, a group
of judges award scores to each athlete. To improve the accuracy of the
scoring, they normally drop the top and bottom score and then compute the
average. (Yes, there are many variants thereof.) We’ll call this a
*robust average*.

In this problem, we will work incrementally to build some portions of a program that calculate an overall score from several judges for a diver’s performance. In addition, we want the program to work for the scores provided for any diver, so we will generalize the operations with a form of subroutine.

Furthermore, we want the output to be easily readable and meaningful, so we will do some numeric processing to convert the precise scores into something more humanly intelligible.

In the reading on the parts of algorithms, we learned that we can write named subroutines take named inputs. While we have not yet learned how to write our own subroutines (“procedures”, in Scheme), we do have an easy way to import named values from different programs.

Say we have a simple list called `contestant-scores`

that contains each judge’s score for one of the contestants. Therefore the beginning of your `.rkt`

file might be the following.

```
#lang racket
(define contestant-scores (list 10 9 10 8 9))
```

We will now calculate the average of the judges’ scores after dropping the
lowest and highest score, and call it `robust-average`

. The following steps
will help you solve the problem incrementally.

### Part A: Finding the robust average

- Remark
- You may want to review the reading on simple lists before working through the following parts.

i. Write a definition that assigns the name `total-score`

to a
*computed* sum of all the scores in the list `contestant-scores`

. (That is,
`total-score`

should remain correct, even if we change the list
`contestant-scores`

.)

```
(define total-score ...)
```

ii. Write a definition that assigns the name `average-score`

to a
*computed* average of the scores by the usual means.

```
(define average-score ...)
```

iii. Write a definition that assigns the name `highest-score`

to a
*computed* highest score.

iv. Write a definition that assigns the name `lowest-score`

to a *computed* lowest score.

v. Write a definition that assigns the name `robust-average`

to the
robust average score (that is, the score that results from dropping
the lowest and highest scores and then averaging the result).

vi. To complete the notion that your solution operates like a subroutine, try running your code on multiple lists of scores, and verify that the results you generate are different and correct.

### Part B: Cleaner averages

The averaged scores you may have seen so far may not be all that pretty. Instead of the 22/3 you might get for contestant A, we’d probably prefer 7.3 (which is an approximation of 7.3333333333333…, the decimal representation of 22/3).

You may recall that we have a number of mechanisms for rounding
real numbers to integers, such as `ceiling`

and `floor`

. But what
if we want to round not to an integer, but to only one digit after
the decimal point? Scheme does not include a built-in operation for
doing that kind of rounding. Nonetheless, it is fairly straightforward.

i. Add instructions to your program that calculate a version of
`robust-average`

rounded to the nearest tenth.

ii. Now, let’s generalize your instructions to round to an arbitrary number of digits after the decimal point.

Suppose `precision`

is a non-negative integer and `robust-average`

is the value you computed above. Write another set of instructions
for rounding `robust-average`

to use exactly `precision`

digits
after the decimal point.

```
> (*your-instructions* ... robust-average ... precision ...)
```

As you write your instructions, you may find the `expt`

function
useful. `(expt b p)`

computes (that
is, `b`

raised to the power `p`

).

## Evaluation

We will primarily evaluate your work on *correctness* (does your code
compute what it’s supposed to and are your procedure descriptions
accurate); *clarity* (is it easy to tell what your code does and how
it acheives its results; is your writing clear and free of jargon);
and *concision* (have you kept your work short and clean, rather than
long and rambly).