views:

641

answers:

3

Consider the following BNF defining trees of numbers. Notice that a tree can either be a leaf, a node-1 with one subtrees, or a node-2 with two subtrees.

tree ::= (’leaf number)
| (’node-1 tree)
| (’node-2 tree tree)

a. Write a template for recursive procedures on these trees.

b. Define the procedure (leaf-count t) that returns the number of leaves in t

> (leaf-count ’(leaf 5))

1

> (leaf-count ’(node-2 (leaf 25) (leaf 17)))

2

> (leaf-count ’(node-1
(node-2 (leaf 4)
(node-2 (leaf 2) (leaf 3)))))

3

Here's what I have so far:

;define what a leaf, node-1, and node-2 is
(define leaf list)
(define node-1 list)
(define node-2 list)

;procedure to decide if a list is a leaf or a node
(define (leaf? tree) (number? (car tree)))
(define (node? tree) (pair? (car tree)))

(define (leaf-count tree)
 (cond ((null? tree) 0)
        ((number? tree) 0)
        ((leaf? tree) 1)
        (else (+ (leaf-count (car tree))
                 (leaf-count (cdr tree))))))

It looks like it should run just fine, but when I try to run it using a simple test case like

(leaf-count '(leaf 5))

I get the following error message:

car: expects argument of type pair; given leaf

What does this error message mean? I am defining a leaf as a list. But for some reason, it's not seeing that and gives me that error message.

+2  A: 

Solving other people's assignments is fun, indeed.

(define leaf-count
  (match-lambda 
   [(list 'leaf x)     1]
   [(list 'node-1 t)   (leaf-count t)]
   [(list 'node-2 l r) (+ (leaf-count l) (leaf-count r))]))
Felix Lange
Thanks for the reply but I can't get it to run. I get the error message "reference to undefined identifier: match-lambda".Could you explain what "match-lambda" does?
Javier
Which language level are you running in? `match-lambda` is part of the 'scheme' language, so you should have `#lang scheme` at the top of your DrScheme definitions window. You can read more about `match-lambda` in the PLT Scheme guide (http://docs.plt-scheme.org/guide/match.html).
Felix Lange
By the way, the language I'm using is a teaching language required for the course based on the book "Essentials of Programming Languages" 3rd Edition by Friedman and Wand.
Javier
A: 

Here's what I have so far:

 ;define what a leaf, node-1, and node-2 is
(define leaf list)
(define node-1 list)
(define node-2 list)

;procedure to decide if a list is a leaf or a node
(define (leaf? tree) (number? (cadr tree)))
(define (node? tree) (pair? (cadr tree)))

(define (leaf-count tree)
 (cond ((null? tree) 0)
        ((number? tree) 0)
        ((leaf? tree) 1)
        (else (+ (leaf-count (car tree))
                 (leaf-count (cdr tree))))))

I got it to work with a minor adjustment: change the conditionals to check the cadr of the list as that is what contains the info. The car of the list in this case is just the label of what the data is (leaf, node, etc.). Not quite. I got it to work for the most basic of test cases, but not for more complex ones like

(leaf-count '(node-2 (leaf 25) (leaf 17)))
Javier
By the way, the language I'm using is a teaching language required for the course based on the book "Essentials of Programming Languages" 3rd Edition by Friedman and Wand.
Javier
This fixes the example, but won't work more generally. The fundamental issue is that your program assumes trees are made one way, and your test program makes them a different way. Try running (leaf 5) and then '(leaf 5) to see the difference.
Noah Lavine
the tests are provided by the instructor. I have to make it accept that at as an input.
Javier
+1  A: 

You've quoted leaf, (leaf-count '(leaf 5)) so it's a symbol, not a variable you've defined earlier. That's the cause of the error, but not the thing you should fix. Your three defines have no much sense and your procedures to detect leaf or node do not match the BNF specification.

Here is a tree from your own example: ’(node-1 (node-2 (leaf 4) (node-2 (leaf 2) (leaf 3)))). It's quoted so node-1, node-2 and leaf are just symbols and need not to be defined. Now write leaf? and node? functions that could detect what the various elements of above tree are. Here is a test case for you where all the function calls should return true:

(define a-tree ’(node-1 (node-2 (leaf 4) (node-2 (leaf 2) (leaf 3)))))
(node? a-tree)
(node? (car (cdr a-tree)))
(leaf? (car (cdr (car (cdr a-tree)))))
(node? (car (cdr (cdr (car (cdr a-tree))))))
(leaf? (car (cdr (car (cdr (cdr (car (cdr a-tree))))))))

Once this works, counting should be no problem either (altough your current method wouldn't work, I propose writing left-subtree and right-subtree functions to help you with that).

Slartibartfast