recursion to find nulls - scheme

im trying to find the max value in a tree, but I'm having trouble understanding the recursion part of it.
what I have so far
(define mytree '(10 (5(4(2 ()()) (22()())) (21(15()()) (23 ()()))) (11(6()())(13()()))))
(define (leaf mytree)
(and(null?(cadr mytree)) (null? (caddr mytree))))
(define (maxval mytree)
(if (null? mytree)
mytree
(max (leaf(maxval (cadr mytree))) (leaf(maxval (caddr mytree))))))
(maxval mytree)
I'm trying to make the leaf function go through every number in the tree until it gets to the bottom numbers, where it will find the greatest value.

Formatting
Indent code, align subtrees, add space
Name predicate with ? at the end
Use tree instead of mytree
Define abstractions (left-child, right-child instead of cadr-soups)
This is more readable:
(define mytree
'(10 (5 (4 (2 () ())
(22 () ()))
(21 (15 ()())
(23 ()())))
(11 (6 () ())
(13 () ()))))
(define (tree-value tree)
(car tree))
(define (left-child tree)
(cadr tree))
(define (right-child tree)
(caddr tree))
(define (leaf? tree)
(and (null? (left-child tree)
(null? (right-child tree))))
(define (maxval tree)
(if (null? tree)
'()
(max (leaf? (maxval (left-child tree)))
(leaf? (maxval (right-child tree))))))
Recursive algorithm
The maximum value of a tree (maxvalue tree) is the maximum value among:
the value associated with the tree: (tree-value tree)
the maximum value of its left subtree: (maxvalue (left-child tree))
the maximum value of its right subtree: (maxvalue (right-child tree))
The degenerate case (base case) where a tree has no child is to return the value associated with the tree.
Your current algorithm does not do that. In particular:
Why is the result of leaf? given to max?
Why don't you check the value rooted at current tree?
You should be able to translate the above in terms of code. This should look roughly like this (untested):
(define (maxval tree)
(if (leaf? tree)
(tree-value tree)
(max (tree-value tree)
(maxval (left-child tree))
(maxval (right-child tree)))))

Short version: you need a data definition, and test cases.
Your data definition should probably read
;; a binary tree is either:
;; -- <you fill in this part>, or
;; -- <you fill in this part too>
Then, you need test cases.
write a test case for both cases of your data definition.
This should answer your question for you.
(In general, the stepper can be helpful, but in this case, I think the problem starts earlier.)

Related

how do you sum tree in scheme

;; A [BT X] is one of
;; - 'leaf
;; - (make-node X [BT X] [BT X])
(define-struct node (val left right))
;; interpretation: represents a node with a value
;; a left and right subtree
(define (tree-sum tree)
(cond
[(symbol=? tree 'leaf) ...] ;; the value remains same
[(node? tree)
(+ (tree-sum (node-val tree))
(tree-sum (node-left tree))
(tree-sum (node-right tree)))]))
not quite sure if i'm on the right track.
Normally, A pair tree is either
a leaf (not a pair), or
a pair, whose car and cdr values are pair-trees.
recursive summing procedure will have to deal with these two cases:
a numbers, i.e., leaves of a tree of numbers, and
pairs, in which case it should sum the left and right subtrees, and add those sums together.
Therefore,
(define (pair-tree-sum pair-tree)
(cond
[(number? pair-tree)
pair-tree]
[else
(+ (pair-tree-sum (car pair-tree))
(pair-tree-sum (cdr pair-tree)))]))
You can split the function into two parts - one that converts the tree into a list of numbers, and another that just uses foldl with that list, and foldl has the advantage of automatically doing the summation as an accumulator.
(define (tree->list tree)
(if (pair? tree)
(append (tree->list (car tree))
(tree->list (cdr tree)))
(list tree)))
(define (tree-sum tree)
(foldl + 0 (tree->list tree)))
You first need to check if the tree is empty, then if its not a list, else you call the function sum to the car of the list, and add to the cdr of the list.
(define (sum tree)
(cond [(empty? tree) 0]
[(not (list? tree)) (if (number? tree) tree 0)]
[else (+ (sum (first tree)) (sum (rest tree)))]))

add nodes to a tree in scheme

Defined in Scheme one (sumanodos-pareja-tree tree) function that takes a tree
generic and returns a new generic tree where each datum is a pair containing the data
Original (left) and the sum of its children nodes (right):
I do this:
(define (sumanodos-pareja-tree tree)
(let ((bosque-sumados (map sumanodos-pareja-tree (hijos-tree tree))))
(make-tree (cons (dato-tree tree) (suma-datos-raiz bosque-sumados))
bosque-sumados)))
(define (suma-datos-raiz bosque-sumados)
(if (null? bosque-sumados) 0
(let ((primer-arbol (car bosque-sumados)))
(+ (car (dato-tree primer-arbol))
(cdr (dato-tree primer-arbol))
(suma-datos-raiz (cdr bosque-sumados))))))
(define tree22 '(2 (7 (1 (10) (4))
(5))
(6 (2 (3)))
(4)))
(sumanodos-pareja-tree tree22)
But it returns this error;
cons: second argument must be a list, but received 2 and 42
as I can do?
This is a restriction of some Racket learning languages. Use list instead of cons.

Confused about binary search trees (Scheme)

I have a problem that I need to complete:
We can represent a nonempty binary tree by list (root left_subtree
right_subtree) and the empty tree by the empty list. Each binary
search tree with integer labels can be considered representing a set
of integers. Write a function which, given a set of integers S as a
bst and an integer x, returns both the set of all the integers less
than x and that of all the integers greater than x as bst’s. Use a
pair rather than a list to represent the resulting sets.
I'm very new to Scheme. I've built trees using SML as well as prolog, but can't seem to get a hold of what I need to do for Scheme. Could anyone help me out and guide me towards this goal? Is my tree suppose to just look like this?
(list value left right)
Yes, that's one way to define a tree. Just so long as you make a proper ADT and use it consistently, it shouldn't matter after you've defined it.
(define (make-tree root left right)
(list root left right))
(define (right tree)
(caddr tree))
(define (left tree)
(cadr tree))
(define (root tree)
(car tree))
(define (empty-tree? tree)
(null? tree))
(define empty-tree '())
(define (leaf? tree)
(and (empty-tree? (left tree)) (empty-tree? right tree)))
(define (split-tree-at tree x)
(let ((less ...)
(more ...))
(cons less more))
(define (in-tree-below-x tree x) ;;assuming a sorted tree
(cond ((empty-tree? tree) (empty-tree))
((>= (root tree) x)
(in-tree-below (left tree) x))
(else (make-tree (root tree)
(left tree)
(in-tree-below-x (right tree) x)))))

Tree sorting function in Scheme

Im struggling with this problem for over 2 days now and still somehow I cannot solve it.
I have to write a function in SCHEME that takes a list in a tree and displays items in sorted order.
The way I define trees is '(6 (left... ) (right...))
My function to choose a tree:
(define (tree-sort tree)
(cond ((null? tree) '())
((> (car tree) (cadr tree))
(tree-sort (cadr tree)))
(else
(tree-sort (caddr tree))))
)
So I guess I should also have a function that sorts the most indepth list?
I really dont get it and this is the last time I will ever have to deal with scheme. I have never used stackoverflow so please excuse me if the formating is wrong.
Kindly thank you!
Now that you clarified that the tree is already sorted, then you're looking for an in-order traversal of the tree, which returns a sorted list of the elements - I'm assuming that you're interested in a list as the output, because of the base case shown in the question. Try something like this:
(define (tree-sort tree)
(if (empty-tree? tree)
'()
(append (tree-sort (left-subtree tree))
(list (value tree))
(tree-sort (right-subtree tree)))))
Use the appropriate procedures for testing if the tree is empty and for accessing each node's value, left and right subtrees. The above procedure will return a sorted list with the trees' values.

Scheme binary search tree

I have already defined helper functions to be:
;; returns value of node
(define (value node)
(if (null? node) '()
(car node)))
;; returns left subtree of node
(define (left node)
(if (null? node) '()
(cadr node)))
;; returns right subtree of node
(define (right node)
(if (null? node) '()
(caddr node)))
and I am trying to write a function leaves that returns a list with the leaves of the tree in order of left to right.
(define (leaves tree)
(if (and (?null (left tree)) (?null (right tree)))
???
(leaves (left tree)) (leaves (right tree))))
but that is as far as I can get
ex: (leaves '(1 (2 () ()) (3 () ()))) should evaluate to '(2 3)
In what you have so far, the ??? is going to need to evaluate to the value of the leaf, ie. (value node) because it is the base case of your iteration. Also, you're going to need to combine the values you get back from the base case in your iteration case. list is usually a good first candidate to try when you need to combine multiple results cons is usually my second try. Taking those suggestions, your leaves function looks like this:
(define (leaves tree)
(if (and (null? (left tree)) (null? (right tree)))
(value tree)
(list (leaves (left tree)) (leaves (right tree)))))
which, when run on your sample of (leaves '(1 (2 () ()) (3 () ()))) does indeed evaluate to (2 3).
HOWEVER; YOU'RE NOT DONE! We're only testing with 1 level of recursion. What if we make a bigger tree? Something like: (leaves '(1 (2 (4 () ()) (5 () ())) (3 (6 () ()) (7 () ())))) Running this gives ((4 5) (6 7)). Those are the right values in the right order, but we have too much structure in there, too many parenthesis. This is a typical problem you will encounter throughout your scheme career, so let me explain why it happens, and how you can go about attacking the problem.
If look at the two branches of our if form, you'll notice that (value tree) returns an atom, or a number in this case. The else branch takes two of ??? and turns it into a list of ???. We're going to be executing the else branch multiple times - any time we're not in the base case. This means we're going to continue to wrap, and wrap, and wrap into a deeper and deeper list structure. So here's what we do about it.
Lets return a list in our base case, and keep our list flat in the recursion case. To return a list in our base case it is as simple as returning (list (value tree)) instead of just (value tree). In the recursion case, we need a function that takes 2 lists and combines them without making a deeper list. Such a function does exist - append. So let's look at what our leaves function looks like now:
(define (leaves tree)
(if (and (null? (left tree)) (null? (right tree)))
(list (value tree))
(append (leaves (left tree)) (leaves (right tree)))))
Intermezzo - Test cases
Racket has test suite library that has a very low barrier to entry called rackunit. Let's throw together a few quick test cases at the bottom of the file.
(require rackunit)
;;empty tree
(check-equal? (leaves '()) '())
;;simple balanced tree
(check-equal?
(leaves '(1 (2 () ()) (3 () ())))
'(2 3))
;;larger balanced tree
(check-equal?
(leaves '(1 (2 (4 () ()) (5 () ())) (3 (6 () ()) (7 () ()))))
'(4 5 6 7))
;;unbalanced tree
(check-equal?
(leaves '(1 (2 (4 () ()) ()) (3 () ())))
'(4 3))
Recently, racket has added support for submodules and specific support for test submodules if you are curious and want to look into them.
Back to our leaves problem. Running our tests, we notice our function doesn't behave well on unbalanced trees. We get extra ()s when we have a node that only has 1 leaf. That is because we are traversing both the left and the right subtrees whenever we're at a node that isn't a leaf. What we really need are two more cases in our if. We could nest the ifs, but scheme's cond form makes better sense.
Now, the template we're aiming to fill out is:
(define (leaves tree)
(cond [(leaf? tree) (...)]
[(and (has-left? tree) (has-right? tree))
(...)]
[(has-left? tree) (...)]
[(has-right? tree) (...)]
[else (error "should never get here")]))
I'll stop there in-case this is homework, and to give you the satisfaction of understanding and solving this the rest of the way. I hope my explanations have given you more direction that just "here's the code" answers.
Well this seems like you're doing Breadth First Search but with the alteration that you don't print yourself if you have two children (or just one, if you don't want to print nodes that only have one child).
I would aim for solving that first, and then changing your solution to that to solve this problem.
(define (list-of-leaves tree)
(if(leaf? tree)
(list (node tree))
(cond((right-branch-only? tree)(list-of-leaves (right-branch tree)))
((left-branch-only? tree)(list-of-leaves (left-branch tree)))
(else(append (list-of-leaves (left-branch tree))
(list-of-leaves (right-branch tree)))))))

Resources