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.5underweight
    18.5 ≤ BMI < 25.0normal
    25.0 ≤ BMI < 30.0overweight
    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.