CSCI 275
Lab 04: Higher Order Functions Fold, Map and Apply
Due Monday, March 23 at 11:59 PM
Part 1 -- Fold
In each of the following you can
use either of the folds we have discussed: foldl or foldr
o
(index 3 (2 4 3 1 2 3)) returns 2
o
(index 3 (2 4 6 4 2)) returns -1
o
(replace 3 5 '(1 2 3 4 5 4 3 2 1)) returns (1 2 5 4 5 4 5 2 1)
o
(replace 3 5 ( 2 4 6 8)) returns (2 4 6 8)
Part 2 -- Trees
For the rest of this assignment
you will write a number of procedures that involve
trees. Recall that a tree is a data structure that is either empty,
or contains some data and has a list of children, each of which is a
tree.
We will use Scheme procedures to
implement the data type. At the beginning of the following section the tree
datatype will be defined. All of this code is
contained in the file "TreeDatatype.rkt". Your
solution file should start with the lines
#lang
racket
(require "TreeDatatype.rkt")
You will need to download the
file TreeDatatype.rkt Please include this file in
your handin folder.
Introduction -- the tree
structure
A tree is either
This leads immediately to the
following functions. All
of the code in boldface is in the TreeDatatype.rkt
file:
(define tree? (lambda (t)
(or (empty-tree? t) (non-empty-tree? t))))
(define empty-tree?
(lambda (x) (null? x)))
(define non-empty-tree? (lambda (x)
(cond
[(list?
x) (eq? (car x) 'tree)]
[else #f])))
; constructors
(define non-empty-tree
(lambda (value list-of-children)
(list
'tree value list-of-children)))
(define empty-tree (lambda
() null))
When actually constructing trees, the non-empty-tree constructor requires us to make an explicit list of children. For example, if we have already made trees t1, t2, and t3 and we want to make a new tree with value 0 and those three previously-made trees as its children we would need to say (non-empty-tree 0 (list t1 t2 t3)). The following alternative constructor allows us to say (make-tree 0 t1 t2 t3). Be careful using this in your recursions. When recursing you probably already have the children as a list, so you will use the non-empty-tree constructor.
; Convenience
constructor
(define makeTree (lambda l
(non-empty-tree (car l) (cdr l))))
; utility functions
(define value (lambda
(tree)
(cond
[(empty-tree?
tree) 'error]
[else
(cadr tree)])))
(define list-of-children
(lambda (tree)
(cond
[(empty-tree?
tree) 'error]
[else
(caddr tree)])))
(define number-of-children
(lambda (tr)
(cond
[(empty-tree?
tree) 'error]
[else
(length (list-of-children tr))])))
(define leaf? (lambda (tr)
(cond
[(empty-tree?
tree) 'error]
[else
(zero? (number-of-children tr))])))
; example trees
(define Empty
(empty-tree))
(define T1 (makeTree 50))
(define T2 (makeTree 22))
(define T3 (makeTree 10))
(define T4 (makeTree 5))
(define T5 (makeTree 17))
(define T6 (makeTree 73 T1 T2 T3))
(define T7 (makeTree 100 T4 T5))
(define T8 (makeTree 16 T6 T7))
For example, here is a picture of
T8 showing the others as subtrees:
Trees T1 through T8 and all of the
code above is in file TreeDatatype.rkt
Tree Exercises
In the exercises that follow, you
should use higher-order functions like map, apply,
and fold to make your solution as concise as possible. You
should also use letrec to define
any recursive help functions.
All programs should be written
using the tree operators defined above. Don't directly manipulate the list
representations; use the tree procedures.
As usual, if the solution to an
earlier problem is useful in a later one, go ahead and use it.
In all of
these tr is a value of the tree datatype
o
(childSum T8) returns 173
o
(childSum T6) returns 82.
o
(allSum T8) returns; 293
o
(allSum T6) returns 155
o
(sizeof T8) returns 8
o
(sizeof T6) returns 4
o
(height T1) returns 0
o
(height T8) returns 2
o
(count 22 T8) returns 1
o
(count 7 T8) returns 0
Each
of the next two procedures produces a flat list of the values in the tree. They
differ only in the order in which the values are listed:
o
(preorder T8) returns (16 73 50 22 10 100 5 17)
o
(postorder T8) returns (50 22 10 73 5 17
100 16)