I am trying to write an inorder traversal without using append, here is my code
(define inorder
(lambda (tree)
(define inorder-iter
(lambda (tree list)
(if (empty-tree? tree)
list
(cons (inorder-iter (left-subtree tree)
(root tree)
(inorder-iter (right-subtree tree) list)))))
(inorder-iter tree '() )))
(define empty-tree? null?)
(define root car)
(define left-subtree cadr)
(define right-subtree caddr)
tree-1
(9
(6 (5 () ()) ())
(18 (11 () (13 () (17 () ()))) (65 (52 (41 (39 () ()) ()) ()) (99 () ()))))
When I call (inorder tree-1)
I get (((5 . 6) . 9) (11 13 17 . 18) (((39 . 41) . 52) . 65) 99) which looks absolutely terrible. What I am trying to get is '(5 6 9 11 13 17 18 39 41 52 65 99). What exactly am I doing wrong? Thank you!
You have several problems with your parentheses. Also notice that you're not using the list parameter - even more, it's poorly named, because it clashes with a built-in procedure.
The question requires that we don't use the built-in append function, but a simple cons won't work. Here's a possible solution:
(define inorder
(lambda (tree)
(define inorder-iter
(lambda (tree lst)
(if (empty-tree? tree)
lst
(inorder-iter (left-subtree tree)
(cons (root tree)
(inorder-iter (right-subtree tree)
lst))))))
(inorder-iter tree '())))
It works as expected:
(inorder tree-1)
=> '(5 6 9 11 13 17 18 39 41 52 65 99)
Related
'(6 (3 (2) (5)) (7 () (9))) is a sorted binary tree
Write a recursive function tree-insert that takes a tree and a number and returns the tree with the number inserted.
(tree-insert 8 '()) should return ‘(8)
(tree-insert 5 ‘(8)) should return ‘(8 (5))
(tree-insert 3 '(6 () (7))) should return '(6 (3) (7))
(tree-insert 4 '(6 (3) (7))) should return '(6 (3 () (4)) (7))
The first thing to do when dealing with a problem like this is to realise that programming as if conses were all there is is not a good idea: it makes for code which is hard to understand and hard to write. You are processing a sorted binary tree which happens to be represented as a tree of conses. So first of all write some abstractions. Unfortunately the representation of the tree is kind of irregular: (9) is the same as (9 ()) is the same as (9 () ()), and the question wants you to return the shortest version, so the abstractions need to cope with that.
Empty nodes, and the value of a node are easy:
(define empty-node '())
(define empty-node? null?)
(define node-value car)
getting the left and right elements of a node are fiddly and I have used Racket's nice match facility for this:
(define (node-left node)
(match node
[(or (list _ l)
(list _ l _))
l]
[(list _)
empty-node]))
(define (node-right node)
(match node
[(list _ _ r)
r]
[(or (list _ _)
(list _))
empty-node]))
And finally making a node also needs to deal with the annoying shorthand versions of nodes with empty children:
(define (make-node value (left empty-node) (right empty-node))
(if (empty-node? right)
(if (empty-node? left)
(list value)
(list value left))
(list value left right)))
Once we have these abstractions, then tree-insert becomes essentially trivial to write:
(define (tree-insert n node)
(cond
[(empty-node? node)
(make-node n)]
[(< n (node-value node))
(make-node (node-value node)
(tree-insert n (node-left node))
(node-right node))]
[else
(make-node (node-value node)
(node-left node)
(tree-insert n (node-right node)))]))
The design recipe for functions is:
data definition
stub, signature, purpose
examples/unit tests
template, plan
function definition, testing
From the example binary tree:
'(6 (3 (2) (5)) (7 () (9))) #| 6
/ \
3 \
/ \ \
2 5 7
/ \
9 |#
one could deduce the data definition:
a TreeOfNumber is one of:
- empty
- (list Number TreeOfNumber TreeOfNumber)
where all numbers in first TreeOfNumber <= Number, all in second >
A first example/test could be:
(check-expect (tree-insert 8 '()) '(8 () ()))
and stub with signature and purpose:
(define (tree-insert n ton) ;; Number TreeOfNumber -> TreeOfNumber
;; produce ton with n inserted at correct place
(list n '() '()))
So the function will have the form:
(define (tree-insert n ton) ;; Number TreeOfNumber -> TreeOfNumber
;; produce ton with n inserted at correct place
(cond
[(empty? ton) (list n '() '()) ]
[else ... (list ... ) ]))
Two more examples:
(check-expect (tree-insert 6 '(8 () ())) '(8 (6 () ()) () ) )
(check-expect (tree-insert 10 '(8 () ())) '(8 () (10 () ())) )
can be rewritten as:
(check-expect (tree-insert 6 '(8 () ())) (list 8 (tree-insert 6 '()) '() ) )
(check-expect (tree-insert 10 '(8 () ())) (list 8 '() (tree-insert 10 '()) ) )
which suggests how to complete the definition:
(define (tree-insert n ton) ;; Number TreeOfNumber -> TreeOfNumber
;; produce ton with n inserted at correct place
(cond
[(empty? ton) (list n '() '()) ]
[else
(if (<= n (first ton))
(list (first ton) (tree-insert n (second ton)) (third ton))
(list (first ton) (second ton) (tree-insert n (third ton)))) ]))
A few more tests:
(check-expect (tree-insert 5 '(8 (6 () ()) ())) '(8 (6 (5 () ()) ()) ()) )
(check-expect (tree-insert 6 '(8 (6 () ()) ())) '(8 (6 (6 () ()) ()) ()) )
(check-expect (tree-insert 7 '(8 (6 () ()) ())) '(8 (6 () (7 () ())) ()) )
(check-expect (tree-insert 8 '(8 (6 () ()) ())) '(8 (6 () (8 () ())) ()) )
(check-expect (tree-insert 9 '(8 (6 () ()) ())) '(8 (6 () ()) (9 () ())) )
But other examples in the question omit trailing empty trees,
so introduce a function to strip them:
(define (tree-trim ton) ;; TreeOfNumber -> TrimmedTree
;; produce ton with trailing emptys dropped
(cond
[(empty? ton) empty ]
[(and (empty? (second ton)) (empty? (third ton)))
(list (first ton)) ]
[(empty? (third ton))
(list (first ton) (tree-trim (second ton))) ]
[else
(list (first ton) (tree-trim (second ton)) (tree-trim (third ton))) ]))
(check-expect (tree-trim '(8 (6 () (7 () ())) ())) '(8 (6 () (7))) )
tree-insert could be wrapped by tree-trim to produce the examples in the question;
as another example of combining these functions, one could have:
(define (tree-insert-list lon ton) ;; ListOfNumber TreeOfNumber -> TrimmedTree
;; produce ton with elements of lon inserted, trailing emptys dropped
(cond
[(empty? lon) (tree-trim ton) ]
[else
(tree-insert-list (cdr lon) (tree-insert (car lon) ton)) ]))
(check-expect
(tree-insert-list '(22 25 7 16 8 34 67 7 32 17 8 4 5 3) '())
'(22 (7 (7 (4 (3) (5))) (16 (8 (8)) (17))) (25 () (34 (32) (67)))) )
Welcome to DrRacket, version 8.6 [cs].
Language: Beginning Student with List Abbreviations; memory limit: 128 MB.
All 12 tests passed!
>
(define (tree-insert element tree)
(cond ((empty? tree) (list element))
((and (>= element (car tree)) (empty? (cdr tree)))
(list (car tree) '() (list element)))
((>= element (car tree))
(list (car tree) (cadr tree) (tree-insert (caddr tree) element)))
((empty? (cdr tree))
(list (car tree) (list element)))
(else
(list (car tree) (tree-insert element (cadr tree)) (caddr tree)))))
> (tree-insert 8 '())
'(8)
> (tree-insert 5 '(8))
'(8 (5))
> (tree-insert 3 '(6 () (7)))
'(6 (3) (7))
> (tree-insert 4 '(6 (3) (7)))
'(6 (3 () (4)) (7))
Having trouble translating a matrix where the input would be two lists and the output would be the addition of the second list to every first such as:
(translate '((1 2 3)(4 5 6)(7 8 9)) '(10 20 30))
; -> ((11 22 33) (14 25 36) (17 28 39))
I currently have:
(define (translate matrix1 matrix2)
(if (list? (car matrix1))
(append '() (map + (car matrix1) matrix2))
(translate (cdr matrix1) matrix2)))
I think this will keep appending each car of matrix1 everytime I recursively call to an empty list but I'm only getting my first 'row' to output.
Any input would be greatly appreciated!
That would be as easy as
(define (translate matrix1 matrix2)
(map (lambda (lst) (map + lst matrix2)) matrix1))
Testing
> (translate '((1 2 3)(4 5 6)(7 8 9)) '(10 20 30))
'((11 22 33) (14 25 36) (17 28 39))
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.
Write a function in Scheme that receives as argument of entry a binary search tree of instances of the student structure
, a list of birth years and returns a list of list of codes that indicate which birth dates are provided each year.
example:
This is the binary tree
(make-árbol-bin
(make-estudiante 5 "35889188" "Victor" (make-fecha 10 6 1991) "calle 67 con cra 20" "4444444") (make-
árbol-bin
(make-estudiante 2 "6457234" "Manuel" (make-fecha 12 10 1992) "calle 56 con cra 33" "5555555") (make-árbol-bin
(make-estudiante 1 "94252688" "Estela" (make-fecha 20 5 1993) "calle 4 con cra 2" "3333333") empty empty) empty)
(make-árbol-bin
(make-estudiante 7 "34987678" "Juan" (make-fecha 25 3 1995) "calle 34 con cra 12" "6666666") empty
empty)
)
List years
(list 1992 1991 )
It should return a list of lists of codes:
((list (list 2) (list 5) )
and I did this but I can not make me return the list of the list
(define-struct fecha ( dia mes año))
This is the structure of the student:
(define-struct estudiante ( codigo id nombre fechanaci direccion telefono))
This is the structure of the binary search tree:
(define-struct arbol-bin( estudiante nod-izq nod-der))
I did this
(define (elimina X L)
(if(null? L) '()
(if (equal? X (car L))
(elimina X (cdr L))
(cons (car L) (elimina X (cdr L))))))
(define (busca d tree)
(if (null? tree)
#f
(let ((node (arbol-bin-estudiante tree)))
(let ((n (estudiante-codigo node)))
(let ((fe (estudiante-fechanaci node)))
(if (or(equal? d (fecha-año fe))
(busca d (arbol-bin-nod-der tree)))
n
(busca d (arbol-bin-nod-izq tree))))))))
(define (pert lst tree)
(elimina false (map (lambda (d) (busca d tree)) lst)))
and this
(pert (list 1992 1991 ) tree)
return
(list 2 5)
As I can do to make me return this:
((list (list 2) (list 5) )
help me please!
You cannot make it return ((list (list 2) (list 5))), because that's not a correct Scheme expression. You can make it return (list (list 2) (list 5)) though:
> (list (list 2) (list 5))
'((2) (5))
To do so, in busca, just replace n with (list n):
(define (busca d tree)
(if (null? tree)
#f
(let ((node (árbol-bin-estudiante tree)))
(let ((n (estudiante-codigo node)))
(let ((fe (estudiante-fechanaci node)))
(if (or (equal? d (fecha-año fe))
(busca d (árbol-bin-nod-der tree)))
(list n) ; <------
(busca d (árbol-bin-nod-izq tree))))))))
or
> (list (list (list 2) (list 5)))
'(((2) (5)))
by changing the above line to (list (list n)).
Where does this implementation of the Josephus problem fall short? For those who are unfamiliar with the Josephus Problem, the goal is to delete every 3rd entry from a circularly linked list until only one remains. In this example I am deleting every "mth" value.
(define (joseph lst)
(let ((m (+ 1 (random (length lst)))))
(define (joseph-h i xlst mlst)
(cond ((<= (length xlst) 1) xlst)
((null? (cdr mlst))
(joseph-h i xlst xlst))
((= i m)
(joseph-h 1 (delete (car mlst) xlst) (cdr mlst)))
(else
(joseph-h (+ i 1) xlst (cdr mlst)))))
(joseph-h 0 lst lst)))
(joseph (list 1 2 3 4 5 6 7))
(define (delete v lst)
(cond ((= v (car lst))
(cdr lst))
(else
(cons (car lst) (delete v (cdr lst))))))
I always end up with the last number of the list as the answer. I know that this is not right.
You're taking the algorithm too literally, by creating a list and deleting elements ("killing" people) from it. A simpler solution would be to use arithmetic operations to model the problem, here's a possible implementation, adapted from my own previous answer:
(define (joseph n k)
(let loop ([i 1]
[acc 0])
(if (> i n)
(add1 acc)
(loop (add1 i)
(modulo (+ acc k) i)))))
For example, to see which position survives in the list '(1 2 3 4 5 6 7) after killing every third person, do this:
(joseph 7 3)
=> 4
Wikipedia provides an interesting discussion regarding the possible solutions for this problem, my solution adapts the simple python function shown, after converting it to tail recursion.
I give three solutions at my blog. The most literal version deletes from a list of n items in steps of m, representing the list as a cyclic list:
(define (cycle xs)
(set-cdr! (last-pair xs) xs) xs)
(define (josephus3 n m)
(let loop ((k (- m 1)) (alive (cycle (range 0 n))) (dead '()))
(cond ((= (car alive) (cadr alive))
(reverse (cons (car alive) dead)))
((= k 1)
(let ((dead (cons (cadr alive) dead)))
(set-cdr! alive (cddr alive))
(loop (- m 1) (cdr alive) dead)))
This does the deletions by actually removing the killed elements from the alive list and placing them on the dead list. The range function is from my Standard Prelude; it returns the integers from 0 to n-1:
(define (range first past . step)
(let* ((xs '()) (f first) (p past)
(s (cond ((pair? step) (car step))
((< f p) 1) (else -1)))
(le? (if (< 0 s) <= >=)))
(do ((x f (+ x s))) ((le? p x) (reverse xs))
(set! xs (cons x xs)))))
The original Josephus problem killed 41 men in steps of 3, leaving the 31st man as the survivor, counting from 1:
(josephus3 41 3)
(2 5 8 11 14 17 20 23 26 29 32 35 38 0 4 9 13 18 22 27 31 36
40 6 12 19 25 33 39 7 16 28 37 10 24 1 21 3 34 15 30)
You might also enjoy the other two versions at my blog.