Scheme changing tree values

2019-03-05 11:53发布

问题:

I need to implement a procedure called inverse-tree that receives a tree whose nodes data values are numbers and booleans and returns the equivalent tree whose nodes satisfy the following:

  • If the equivalent node of the original tree is a number, then the resulting tree’s node is −1· that node value
  • If the equivalent node of the original tree is a boolean, then the resulting tree’s node is the logical not of that node value

Examples:

> (inverse-tree ’())
’()
> (inverse-tree ’(5))
’(-5)
> (inverse-tree ’(0))
’(0)
> (inverse-tree ’(#f))
’(#t)
> (inverse-tree ’(#t))
’(#f)
> (inverse-tree ’(-5 (1 (-2) (3) (#f)) (#t)))
’(5 (-1 (2) (-3) (#t)) (#f))

The representation of a (possibly empty or non-complete) tree in Scheme is as follows: the first element in every nesting level represents the root of the sub-tree. The rest of the elements are the children (each of them is a tree, of course). A leaf is represented by a list with only one element (the leaf value). A completely empty tree is represented by the empty list.

more info at Scheme altering tree values.

回答1:

Write down what the possible inputs are (there are three cases in the description of what a tree looks like) and define the result for each case.

Here is the general tree-traversal you need to implement:

  • If the tree is empty:
    • Produce the empty tree
  • If the tree is a leaf:
    • Produce an inverted leaf
  • Otherwise:
    • Invert the node's value
    • Produce a new tree by combining this inverted value with the results of inverting each subtree

You're probably going to want to read about map in your favourite Scheme book.

It's possible (but I suspect that it's a later exercise) to generalise this so it applies an arbitrary function in the tree, just like map does with lists.



回答2:

The explanation for the tree structure doesn't seem to work. (1 (-2) (3) is a node, but 1 is not a parent. However it seems you can look at the whole thing as a binary tree where pairs are nodes and the empty list is an empty tree and any other value is a leaf node.

The abstraction would look like this:

(define make-tree cons)
(define tree-left car)
(define tree-right cdr)
(define tree? pair?)
(define empty-tree '())

You can map over the values of a tree like this:

(define (map-tree proc tree)
  (cond ((eq? empty-tree tree) empty-tree)
        ((tree? tree) 
         (make-tree (map-tree proc (tree-left tree))
                    (map-tree proc (tree-right tree))))
        (else (proc tree))))

Example:

(map-tree (lambda (v) (+ v 1)) '(1 (2) 3))
; ==> (2 (3) 4)

Obviously you need to replace the first argument with a procedure that works like this:

(inverse #f) ; ==> #t
(inverse #t) ; ==> #f
(inverse 5)  ; ==> -5
;; optional
(inverse 'xxx) ; ==> xxx

Then it's easy to make your procedure:

(define (inverse-tree tree)
  (map-tree inverse tree))

(inverse-tree ’(-5 (1 (-2) (3) (#f)) (#t)))
; ==> (5 (-1 (2) (-3) (#t)) (#f))

Now if you cannot use abstractions you would need to use the substitution rules. eg.

(define (tree-inc v)
  (map-tree (lambda (v) (+ v 1)) v))

; ==
(define (tree-inc tree)
  (cond ((eq? '() tree) '())
        ...
        (else (+ (car tree) 1))))

There you have it. More difficult to read and reason about than one that uses abstractions. Good luck with that.



回答3:

After a lot of digging and understanding the syntax better I cam up with a simple 1 function solution:

(define (inverse-tree tree)
  (cond ((eq? '() tree) '())
        ((pair? tree) 
         (cons (inverse-tree (car tree))
                    (inverse-tree (cdr tree))))
        (else ((lambda(x) (if (boolean? x) (not x) (- x))) tree))))


回答4:

I think that should work:

  (define inverse-tree
  (lambda (tree)
    (if (null? tree)
        '()
        (if (number? (car tree))
            (cons (* -1 (car tree)) (inverse-tree (cdr tree)))
            (if (boolean? (car tree))
                (cons (not (car tree)) (inverse-tree (cdr tree)))
                (cons (inverse-tree (car tree)) (inverse-tree (cdr tree))))))))