Homework 5
More Structurally Recursive Functions

Due: Monday, March 3, at 11:59 PM

Introduction

This assignment asks you to write a few more recursive functions in Racket. Its primary goal is to gain experience with common recursion patterns, especially mutual recursion.

Template Source File

Download these files:

and use them as the starting points for your submission. As usual, please use the names given for your files.

The source file includes a provide clause that exports your five public functions for use by other files. The tests file includes a require clause that imports your functions, enabling it (and you!) to test them with Rackunit. The provide clause also enables me to test your code using my own Rackunit tests.

With provide, you must define all five functions. If you don't have time to solve a problem, define a function that takes the correct number of arguments and returns a legal default value, such as 0 or '(). homework05.rkt includes default functions for each problem that you can use until you write your code.

Do Not Use...

To solve these problems, you do not need any Racket features beyond the things we have learned in class and the things discussed in this assignment. In order to practice the new skills we are learning, do not use...

  • ... any of Racket's primitive higher-order functions, including map, apply, and filter.
  • ... reverse or any Racket function that converts a list argument to another datatype. Process the list one element at a time.
  • ... a let expression or an internal define in any function.

Organizing Code

Put your solutions in homework05.rkt. Use a comment to indicate where the code for each problem begins and ends. The template already does this for you.

Put your tests in homework05-tests.rkt. For each problem, write at least three Rackunit expressions to test your solution. Depending on the type of value that the function produces, use check-equal? or check-true/check-false. You may use one of my examples as one of your tests. Be sure that you test other key cases, too.

Put any helper functions you write for a problem just after the main function in your solution. You are not required to write any helper functions.

Problems

  1. Write a structurally recursive function named (list-of? type? lst) that takes two arguments, a boolean predicate type? and a list lst containing any type of value.
      <list> ::= ()
               | (<anything> . <list>)
      
    list-of? returns true if every item in lst is of type type?. For example:
    ; Eugene is many things.  He is not a number.
    > (list-of? number? '(1 2 3 "Eugene" 4 5))
    #f
    
    You can check the type of a value by applying type? as you would any other function: (type? value).

  2. Write a mutually recursive function named (total-length str-lst) that takes one argument, a string-list.
    <string-list> ::= ()
                    | (<string-exp> . <string-list>)
    
     <string-exp> ::= <string>
                    | <string-list>
    
    total-length returns the combined length of all the strings in str-list. For example:
    > (total-length '("Write" "a" "mutually" "recursive" "function"
                      ("total-length" "str-list")
                      "that" "takes" "one" "argument"
                      ("a" "string-list")))
    83
    
    total-length should be mutually recursive with the function total-length-se, which processes a string expression.

    Recall that Racket provides the function string-length.

  3. Write a mutually recursive function named (rename-course old-name new-name catalog) that takes three arguments, two symbols, old-name and new-name, and a course tree catalog. A course tree is defined as:
    <course-tree> ::= ()
                    | (<course-exp> . <course-tree>)
    
     <course-exp> ::= <symbol>
                    | <course-tree>
    
    rename-course returns a course tree identical to catalog, with each occurrence of old-name replaced by new-name. For example:
    > (rename-course 'cs1510 'cs1160
                     '((cs1120 cs1130 cs1140 cs1150 cs1160 cs1510)
                       cs1510
                       ((cs1410 cs2420) (cs1800 cs2530))))
    '((cs1120 cs1130 cs1140 cs1150 cs1160 cs1160)
      cs1160
      ((cs1410 cs2420) (cs1800 cs2530)))
    
    rename-course should be mutually recursive with the function rename-course-exp, which processes a course and a course-exp.

  4. Write a mutually recursive function named (max-nlist nlist) that takes one argument, an n-list nlist.
        <n-list> ::= ()
                   | (<number-exp> . <n-list>)
    
    <number-exp> ::= <number>
                   | <n-list>
    
    max-nlist returns the largest numbers in nlist. If nlist is the empty list, it returns -1. For example:
    > (max-nlist '(1 5 (1 (7 21)) ((0 21) 3 (4 3) 1)))
    21
    
    max-nlist should be mutually recursive with the function max-num-expr, which returns the largest value in a number expression.

    Recall that Racket provides the variable-arity max function.

  5. Write a mutually recursive function named (prefix->infix binary-exp) that takes one argument, a binary expression in prefix notation.
    <prefix-exp> ::= (<operator> <number-exp> <number-exp>)
    <number-exp> ::= <number>
                   | <prefix-exp>
    
    prefix->infix returns an equivalent infix expression as its value.
     <infix-exp> ::= (<number-exp> <operator> <number-exp>)
    <number-exp> ::= <number>
                   | <infix-exp>
    
    In both kinds of expression, an operator is a symbol. For example:
    > (prefix->infix '(+ 4 5))
    '(4 + 5)
    
    > (prefix->infix '(* (+ 4 5)
                         (+ 7 6)))
    '((4 + 5) * (7 + 6))
    
    prefix->infix should be mutually recursive with the function number-expr->infix, which returns an infix version of a number expression.

Deliverables

By the due time and date, use the course submission system to submit the following files electronically:

Be sure that your submission follows the submission requirements. As always, be sure to use the specified name for your files. This enables the auto-grader to find and run your code.