Insert elements in a BST - racket

I get an error with this code, where i try insert elements of a list into a BST.
The error is tree-value: expects a tree, given 4 but i have no clue why this happens.
(define-struct tree (left right value))
(define example (make-tree
(make-tree empty empty 3)
(make-tree
(make-tree 4 empty 7)
(make-tree empty empty 10) 8)5))
(define app (list 1 2 3 4 6 11 12 13))
(define (insert tree val)
(cond [(empty? tree) (make-tree empty empty val)]
[(= val (tree-value tree)) tree]
[(< val (tree-value tree))
(make-tree (insert (tree-left tree) val) (tree-right tree) (tree-value tree))]
[(> val (tree-value tree))
(make-tree (tree-left tree) (insert (tree-right tree) val) (tree-value tree))]))
(define (insert-list tree lst)
(cond [(empty? lst) tree]
[else (insert-list (insert tree (first lst)) (rest lst))]))
> (insert-list example app)
tree-value: expects a tree, given 4
>

Think about what defines a tree. In your example a tree is one of
What defines a tree.
My interpretation of your code is that a tree is defined as follows:
A tree is one of:
| empty
| (make-tree tree tree number)
If that is the definition you mean, you are not creating a valid tree. Look at the definition of example: (make-tree 4 empty 7) is not valid. You can fix that by changing the definition of example:
(define example (make-tree
(make-tree empty empty 3)
(make-tree
(make-tree empty empty 7)
(make-tree empty empty 10) 8) 5))

You can use DrRacket's stepper to help you understand this problem. Put the code above (along with the (insert-list example app) call) into the definitions window, make sure the language level is set to Beginner, and then click on the Step button. You can use the menu to jump to the last step of the failed evaluation, where you'll see a call to tree-value with 4. How did that happen? Use the step backward button to see the previous step, etc.

The example tree was incorrectly built - a tree was expected, but a number was passed in the node with value 4. Also, a value of 4 there doesn't satisfy the order property of a BST (4 is less than 5, yet you located it to its right). We should change it to a valid value, say - 6. Please use this tree instead:
(define example
(make-tree
(make-tree empty empty 3)
(make-tree
(make-tree (make-tree empty empty 6) empty 7)
(make-tree empty empty 10)
8)
5))

Related

Racket - Produce a new list based on given list

I'm trying to create a new list based on an original list where each element of the list contains the first element from the original list and second element being the product of the second and third element from the original list.
Example: If the original list is
(list (list "A" 2 3) (list "B" 3 4)
Then the result will be
(list (list "A" 6) (list "B" 12))
So far I've written:
(define (total-price-list lol)
(cond
[(empty? lol) empty]
[else (list (price-list (first lol))
(price-list (rest lol)))]))
(define (price-list row)
(list (first row) (* (second row) (third row))))
I don't know how to achieve the wanted result. Can someone help me with my code?
The lambda within the map keeps the first element as is and multiplies the second and the third element of each sublist.
(define (total-price-list lol)
(map (λ (l) (list (first l) (* (second l) (third l)))) lol))
(total-price-list (list (list "A" 2 3) (list "B" 3 4)))
; => '(("A" 6) ("B" 12))

Using racket to recursively sum nested lists within a list of permutations

I have a list of numbers and a list of operators in racket.
(define numList (list 5 25))
(define ops '(+ *))
I am using the cartesian-product to join the operators to each possible permutation of the list of numbers.
(cartesian-product ops (permutations numList))
which gives the following result;
'((+ (5 25))
(+ (25 5))
(* (5 25))
(* (25 5)))
I want to sum each nested list, ie (+ (5 25)) and then add them to a list.
I have managed to do the following so far using the eval keyword;
(define ns (make-base-namespace))
(list (eval
(flatten
(cadr
(cartesian-product ops (permutations numList))))ns ))
Which removes the nesting of each list and performs the sum on the first 3 elements and returns a value of 50 (+ (5 25)).
I want to perform this recursively on each nested section before the flatten is performed. I know that I'll be able to use remove-duplicates too.
I'm new to Racket, but here's what i have so far;
(define (evalCart l)
(if (null? l)
0
(list
(eval
(flatten
(cadr
(cartesian-product ops (permutations numList)))) ns ) (evalCart (car
l)))))
eval is a bit overkill. You can instead determine which procedure you want by comparing for symbol equality. Since racket has first class procedures, you can just return the procedure itself. For instance:
(define (get-procedure term)
(case term
[(+) +]
[(-) -]
[(*) *]
[(/) /]))
If you don't know case you can use a cond form
(cond [(eq? term '+) +] ...
Then you can use this with apply as in
(define (evaluate term)
(define procedure (get-procedure (first term)))
(define arguments (second term))
(apply procedure arguments))
Then you can map the procedure evaluate as in
(map evaluate (cartesian-product ops (permutations numList)))
This will give you a list of numbers. In the case of the list of four elements you gave, you would get '(30 30 125 125), which I believe is what you're looking for.

Reverse the order of pairs

I am trying to write a function in Racket that will reverse the order of pairs. For example, given the list '(1 2) the function should produce '(2 1). Here is my code so far:
(define (reverse aList)
(cons (second aList)
(first aList))
This is not producing the correct answer, however. When I test with '(a b) it returns '(b . a) instead of '(b a). How do I get rid of the period between the b and a?
You should have:
(define (reverse-pair lst)
(cons (second lst) (cons (first lst) empty)))
As stated in Racket's docs:
The cons function actually accepts any two values, not just a list for the second argument. When the second argument is not empty and not itself produced by cons, the result prints in a special way. The two values joined with cons are printed between parentheses, but with a dot (i.e., a period surrounded by whitespace) in between.
So,
> (cons 1 2)
'(1 . 2)
> (cons 1 (cons 2 empty)) ; equivalent to (list 1 2)
'(1 2)

Building a Binary tree in lisp

I'm trying to build a binary tree is lisp. The function should do this
(buildBST ‘(6 9 2 1 7)) -> (6 (2 (1) ()) (9 (7) ()))
The code we have so far will keep returning the error
> 7 nil arguments should be of type real
Here's our code
(defun buildBst (lis)
(cond
((null lis) 0)
((atom lis) lis)
(t (if ( >(car lis)(car(cdr lis)))
(buildBst( cdr lis))
(buildBst(cdr lis))))))
The best approach would be to make an insert function:
(defun tree-insert-element (tree element)
(cond ((tree-null-p tree)
(make-tree element nil nil))
((< (tree-value tree) element)
(make-tree (tree-value tree)
(tree-left tree)
(tree-insert-element (tree-right tree) element)))
(t
(make-tree (tree-value tree)
(tree-insert-element (tree-left tree) element)
(tree-right tree)))))
Thus when you want to insert a whole bunch you can do this:
(defun tree-insert-list (tree list)
(reduce #'tree-insert-element list :initial-value tree))
Of course, you'll need to define the functions the insert function uses as I really don't care how you choose to model a tree. From the look of the expected result I guess make-tree might just wrap list*, but thats not the only way to make a tree!

Recursive range in Lisp adds a period?

(define ..
(lambda (start stop)
(cond ((> (add1 start) stop) (quote ()))
((eq? (add1 start) stop) (sub1 stop))
(else (cons start (.. (add1 start) stop))))))
I have defined a simple range function.
The intent is for
(.. 1 5) --> (1 2 3 4)
Instead, a bizarre period is being added to my tuple and I have no idea why:
(.. 1 5) --> (1 2 3 . 4)
I don't understand why this is happening. Any help is appreciated
A list in Scheme is either the empty list () (also known as nil in some Lisps), or a cons cell whose car (also known as first) is an element of the list and whose cdr (also known as rest) is either the rest of the list (i.e., another list), or an atom that terminates the list. The conventional terminator is the empty list (); lists terminated by () are said to be "proper lists". Lists terminated by any other atom are called "improper lists". The list (1 2 3 4 5) contains the elements 1, 2, 3, 4, and 5, and is terminated by (). You could construct it by
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 ())))))
Now, when the system prints a cons cell, the general case is to print it by
(car . cdr)
For instance, the result of (cons 1 2) is printed as
(1 . 2)
Since lists are built of cons cells, you can use this notation for lists too:
'(1 2 3 4 5) ==
'(1 . (2 . (3 . (4 . (5 . ())))))
That's rather clunky, though, so most lisps (all that I know of) have a special case for printing cons cells: if the cdr is a list (either another cons cell, or ()), then don't print the ., and don't print the surrounding parenthesis of the cdr (which it would otherwise have, since it's a list). So, if you're seeing a result like
(1 2 3 . 4)
it means you've got an improper list that is terminated by the atom 4. It has the structure
(1 . (2 . (3 . 4)))
Now the question is: where in your code did the list construction go awry? .. is always supposed to return a proper list, so let's look at the cases: The first case always returns a proper list (the empty list):
((> (add1 start) stop) (quote ()))
The second case looks like it can return something that's not a list (assuming that (sub1 stop) == (- stop 1)):
((eq? (add1 start) stop) (sub1 stop))
Now, if .. were functioning correctly, then the third case would always be returning a proper list (since (cons x y) is a proper list if y is):
(else (cons start (.. (add1 start) stop)))
Make your second case return a list and you should be all set.
Your expression (sub1 stop) needs to read (list (sub1 stop))
In order for cons to build up a proper list, the second element needs to be a list itself. Thus, your function .. should return a list of some type for every cond clause.
Remove this part of the cond
((eq? (add1 start) stop) (sub1 stop))
It's causing a premature finish.