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
, andfilter
. -
...
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 internaldefine
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
-
Write a structurally recursive function named
(list-of? type? lst)
that takes two arguments, a boolean predicatetype?
and a listlst
containing any type of value.<list> ::= () | (<anything> . <list>)
list-of?
returns true if every item inlst
is of typetype?
. 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 applyingtype?
as you would any other function:(type? value)
. -
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 instr-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 functiontotal-length-se
, which processes a string expression.
Recall that Racket provides the functionstring-length
. -
Write a mutually recursive function named
(rename-course old-name new-name catalog)
that takes three arguments, two symbols,old-name
andnew-name
, and a course treecatalog
. A course tree is defined as:<course-tree> ::= () | (<course-exp> . <course-tree>) <course-exp> ::= <symbol> | <course-tree>
rename-course
returns a course tree identical tocatalog
, with each occurrence ofold-name
replaced bynew-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 functionrename-course-exp
, which processes a course and a course-exp. -
Write a mutually recursive function named
(max-nlist nlist)
that takes one argument, an n-listnlist
.<n-list> ::= () | (<number-exp> . <n-list>) <number-exp> ::= <number> | <n-list>
max-nlist
returns the largest numbers innlist
. Ifnlist
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 functionmax-num-expr
, which returns the largest value in a number expression.
Recall that Racket provides the variable-aritymax
function. -
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 functionnumber-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:
-
homework05.rkt
, the source file containing your function definitions -
homework05-tests.rkt
, the source file containing your test cases
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.