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:

1. All the students in the class line up in an arbitrary order.
2. The instructor erases the whiteboard.
3. We will call the student at the front of the line student A.
4. We will call the student next in line student B.
5. Student B announces their birthday while student A listens.
6. Student A compares their own birthday to student B’s birthday.
7. If both birthdays are on the same day of the year, skip to step 11. If not, continue to step 8.
8. If student B is at the end of the line, go to step 14. Otherwise, continue to step 9.
9. The name “student B” will now refer to the next student in line behind our current student B.
10. Go to step 5.
11. The instructor writes one tally on the whiteboard.
12. Both students A and B exit the classroom.
13. If there is at least one student left in line, go to step 3. Otherwise, continue to step 14.
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.

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 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 $b^p$ (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).