### CSC 533: Programming Languages Spring 2019 HW4: Scheme Programming

For this assignment, you are to define numerous Scheme functions. For simplicity, place all of your function definitions in a single file named YOURNAME-hw4.ss, where YOURNAME is your last name. Be extremely careful to define your functions exactly as described in the assignment. Points will be deducted for syntax discrepancies, such as a misnamed function or rearranged inputs. Also, be sure to include a comment block at the top of the file containing your name and comment each function as to its behavior.

### Part 1: Simple functions

1. Define functions for converting between inches and centimeters, and between pounds and kilograms (and vice versa for each). Recall that 1 inch = 2.54 centimeters and 1 pound = 0.45359237 kilograms. For example, (in->cm 10) should evaluate to 25.4, (cm->in 100) should evaluate to approximately 39.37, (kg->lb 10) should evaluate to approximately 22.05, and (lb->kg 100) should evaluate to approximately 45.36.

2. Body Mass Index (BMI) is often used by doctors and dieticians in assessing the overall health of a patient. The formula is as follows:

```    BMI = (weight in kilograms) / (height in meters)2
```

Define a function named BMI-Metric that takes two inputs, a person's height (in centimeters) and weight (in kilograms), and returns his/her BMI. For example, (BMI-Metric 170.0 70.0) should evaluate to approximately 24.22. Similarly, define a function named BMI-American that takes two inputs, a person's height (in inches) and weight (in pounds), and returns his/her BMI. For example, (BMI-American 65.0 170.0) should evaluate to approximately 28.29. Note: you should be able to make use of the BMI-Metric function here.

3. According to the Center for Disease Control, body mass index correlates to the following weight categories:

 BMI < 18.5 underweight 18.5 ≤ BMI < 25.0 normal 25.0 ≤ BMI < 30.0 overweight 30.0 ≤ BMI obese

Define functions classify-Metric and classify-American that each return a pair, where the first value is the calculated BMI and the second is the CDC classification. For example, (classify-Metric 170.0 70.0) should evaluate to approximately `(24.22 normal)`, while (classify-American 65.0 170.0) should evaluate to approximately `(28.29 overweight)`. Note: you should be able to make use of the BMI-Metric and BMI-American functions here.

### Part 2: Randomness

When called with no inputs, the built-in `random` function returns a pseudo-random real number between 0.0 (inclusive) and 1.0 (exclusive). When called with a single integer as input, `random` returns a pseudo-random integer in the range 0 (inclusive) to that input (exclusive). For example, the call `(random 4)` might return 0, 1, 2, or 3, with equal likelihood. In addition, Racket defines a library of useful randomness functions which can be loaded using `require`. For example, the `noun` function below (with no inputs) uses `random-ref` to randomly select a random word from a list of nouns.

(require racket/random) ;;; Selects a random noun. (define (noun) (random-ref '(girl boy dog ball computer))
1. Enter this function in your file and define similar functions named `verb` and `article`, which select a random verb and article, respectively. Each should have at least five words of the appropriate type to choose from.

2. Define functions named `sentence`, `noun-phrase`, and `verb-phrase`, which generate lists of words as defined by the following grammar rules:

sentence <-- noun-phrase + verb-phrase noun-phrase <-- article + noun verb-phrase <-- verb + noun-phrase

For example, the call `(noun-phrase)` might return `'(the ball)`, the call `(verb-phrase)` might return `'(kicked some ball)`, and the call `(sentence)` might return `'(some girl kicked a ball)`. When defining these functions, you should make use of previously defined functions to simplify code and make changes easier.

3. Modify your `noun-phrase` function so that the article in the noun phrase is optional. For example, it should be possible for `(noun-phrase)` to return `'(ball)` or `'(the ball)`. Similarly, modify your `verb-phrase` function so that the noun phrase component is optional. In both cases, the optional component should have a 50/50 chance of being included. Note that since the `sentence` calls both of these functions, the length of generated sentences may vary considerably, from `'(girl kicked)` to `'(some girl kicked a computer)`.

### Part 3: List Processing

1. Define a function named `num-pos` which takes a list of numbers as input and returns a count of how many of those numbers were positive (i.e., greater than 0). For example, `(num-pos '(0 -3.2 88 -0.11 3.2))` would return 2.

2. Define a function named `num-between` which takes a list of numbers and two numbers (defining a range) as input. The function returns a a count of how many of those numbers were in the specified range. For example, `(num-between '(0 -3.2 88 -0.11 3.2) 0 10)` would return 2. Assume the boundaries of the range are inclusive, so 0 is considered to be in the range from 0 to 10. To simplify this task, you may assume that the range values are specified in non-decreasing order (i.e., the first numberin put is the lower bound and the second is the upper bound).

3. Define a function named roman->num that takes one input, a list of characters representing a roman numeral, and returns the number value represented by that roman numeral. For example, (roman->num '(X V I)) should evaluate to 16. The following is a list of the roman letters and numbers they represent:

M = 1000, D = 500, C = 100, L = 50, X = 10, V = 5, I = 1.

You may assume the ancient roman style of writing letters, where 4 is represented IIII and 90 is represented LXXXX. A harder problem, which you may attempt if you like, is to use the modern roman style where 4 is IV and 90 is XC.

4. Define a function named num->roman that performs the reverse conversion, from a number to a list of characters representing a roman numeral. For example, (roman->num 66) should evaluate to '(L X V I). Again, you may assume the ancient roman style of writing letters.

### Part 4: Simulations

The function below can be used to simulate the random flip of a coin, returning either `'heads` or `'tails` with equal likelihood.

;;; Simulates a coin flip. (define (coin-flip) (if (< (random) 0.5) 'heads 'tails))
1. Define a function named `head#` that simulates a specified number of coin flips and returns the number of those flips that were heads. For example, the call `(head# 1000)` would simulate 1,000 flips and return the number of heads, e.g., 508. Since the desired number of flips could be extremely large, your function should only utilize tail-recursion.

2. Define a function named `head%` that simulates a specified number of coin flips and returns the percentage of those flips that were heads. For example, the call `(head% 1000)` would simulate 1,000 flips and return the percentage of heads, e.g., 50.8. In the special case where the number of flips is 0 or negative, we will say that the heads percentage is 0.0. Note: you should be able to make use of the head# function here.