Functional Problem Solving (CSC 151 2014F) : Assignments

Assignment 2: Starting Scheme by Scoring Swimmers


Due: 10:30 p.m., Tuesday, 9 September 2014

Summary: We consider some initial problems that you will solve with the Scheme programming language.

Purposes: To get you used to writing Scheme. To get you started thinking about algorithm design. To encourage you to do work outside of class.

Collaboration: You must work with assigned partners on this assignment. The partner assignments are available at http://www.cs.grinnell.edu/~rebelsky/Courses/CSC151/2014F/partners/assignment.02.html. You may discuss this assignment with anyone, provided you credit such discussions when you submit the assignment.

Wrapper (Prologue): Individually read through this assignment and make sure that you understand what is required. Then use the form available at http://bit.ly/151hw2pro to indicate (a) how long you think this assignment will take and (b) what you think will be the most challenging aspect of this assignment.

Wrapper (Epilogue): When you are done with the assignment, fill out the form available at http://bit.ly/151hw2epi to indicate (a) how long the assignment took, (b) what the most challenging part of the assignment was, and (c) something important you learned from doing the assignment. If you find that the assignment took much less or much more time than you expected, also include (d) a note as to what might have led to that difference.

Submitting the main assignment: Email your answer to . The title (subject) of your email should have the form CSC 151.01 Assignment 2: Starting Scheme and the e-mail should contain your answers to all parts of the assignment. Scheme code and your answer for problem 4 should be in the body of the message. For the Scheme code, you need only submit the contents of assignment2.rkt.

Warning: So that this assignment is a learning experience for everyone, we may spend class time publicly critiquing your work.

Assignment

In this assignment, 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.

Finally, swimmers' times will also be measured, and we will need a way to add times together.

Part A: Robust Averaging

So far we have learned that named subroutines take named parameters. While we have not yet learned how to write our own subroutines (procedures), we do have an easy way to import named values from different programs.

Say we define the file contestantA.rkt with the following contents representing each judge's score for the first contestant.

#lang racket
(provide (all-defined-out))
(define judge1  7)
(define judge2 10)
(define judge3  5)
(define judge4  8)
(define judge5  6)
(define judge6  9)
(define judge7  8)
(define judge8  6)

If the file assignment2.rkt is saved in the same folder as contestantA.rkt, we can load the data and, say, calculate the average of the first two judges' scores as follows.

#lang racket
(require (file "contestantA.rkt"))
(/ (+ judge1 judge2) 2)

Running this program would likely produce the following result.

17/2

Of course, that's incomplete as a score. To find the complete score in a way that is robust to outliers, we will calculate the average of six judges' scores after dropping the lowest and highest score, and call it robust-average. The following steps will help you solve the problem incrementally.

1. Write a definition that assigns the name total-score to a computed total of all the scores. (That is, total-score should remain correct, even if we change the values associated with judge1 through judge8.)

2. Write a definition that assigns the name average-score to a computed average of the scores by the usual means.

3. Write a definition that assigns the name highest-score to a computed highest score.

4. Write a definition that assigns the name lowest-score to a computed lowest score.

5. 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).

6. To complete the notion that assignment2.rkt operates like a subroutine, create a few more contestant files, change the require statement, and verify that the results you generate are different and correct.

Part B: Rounding

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.

1. Add instructions to your program that calculate a version of robust-average rounded to the nearest tenth.

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

Part C: Adding Times

The swim team also needs a program to tally the times for members' events. Suppose the values time-1-min, time-1-sec, time-2-min, and time-2-sec represent the times of two swimmers - swimmer 1 took time-1-min minutes and time-1-sec seconds and swimmer 2 took time-2-min minutes and time-2-sec. You can assume that all of these times are sensible values (i.e., positive integers, with seconds in the range 0 to 59, inclusive).

Write a definition that assigns the names time-total-min and time-total-sec to the computed sum of the two times. For example, if swimmer one took 2 minutes and 15 seconds and swimmer two took 2 minutes and 11 seconds, then the total time is 4 minutes and 26 seconds. Similarly, if swimmer one took 2 minutes and 35 seconds and swimmer two took 2 minutes and 36 seconds, then the total time is 5 minutes and 11 seconds. As the second example suggests, you will need to keep the seconds' sum in a sensible range.

Part D: Explaining Addition

In many of your expressions above, you relied on Scheme's built-in addition operation. But what if Scheme didn't know how to add numbers? We'd have to teach it to do so. Don't worry, we're not going to make you write a Scheme program to add numbers. However, it is useful to think about how you describe addition, say to a species that we discover is sentient, but has never thought about mathematics.

Write English instructions that teach someone how to add two one-digit or two-digit non-negative whole numbers. You should not assume that your audience has any intrinsic understanding of what the numbers represent, although you can ask them to determine whether there is only one digit (e.g., the number 5) or two digits (e.g., the number 42) and to make a choice based on that question. You may assume that your audience knows some basic concepts, such as left and right.

Hint: You may find it easier to start by thinking about how you'd teach someone to add two one-digit numbers.

Important Evaluation Criteria

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