Racket: given the seller name, print the result of the products sold in a binary tree - binary-tree

the goal of the code is when i type the name of the seller the output must be the quantity of the product sold
(define-struct node (seller_info left_tree right_tree))
(define-struct seller (name quantity_sold))
(define treeSellers (make-node (make-seller "laura" 8)
(make-node (make-seller "pedro" 5)empty empty)
(make-node (make-seller "laura" 10)empty empty)
)
)
(define (addTree sellerName tree)
(cond
[(empty? tree) empty]
[(string=? sellerName (seller-name (node-seller_info tree)))
(+ (seller-quantity_sold (node-seller_info tree)))]
[else (addTree sellerName (node-left_tree tree))
(addTree sellerName (node-right_tree tree))]
)
)
the output must be
(addTree "laura" treeSellers) 18
but is instead
(addTree "laura" treeSellers) 8
Any suggestions to cause the output to go the wanted one?

There are three main problems with your code:
The base case is wrong, you can't return empty, the answer is supposed to be a number, not a list. You must return zero here.
Once you find a match, you stopped the recursion - but there could be more matches, you have to keep looking.
In the else case, you're not adding together both results, in effect, you discard the value of the left subtree and only return the value of the right subtree.
This should fix all the issues:
(define (addTree sellerName tree)
(cond
[(empty? tree) 0]
[(string=? sellerName (seller-name (node-seller_info tree)))
(+ (seller-quantity_sold (node-seller_info tree))
(addTree sellerName (node-left_tree tree))
(addTree sellerName (node-right_tree tree)))]
[else
(+ (addTree sellerName (node-left_tree tree))
(addTree sellerName (node-right_tree tree)))]))
Now it works as expected:
(addTree "laura" treeSellers)
=> 18
(addTree "pedro" treeSellers)
=> 5
(addTree "ivan" treeSellers)
=> 0

Related

When I doing tree-depth function, it got a mistake

I got a error, when I run it always say:
tree-node-left: contract violation
expected: tree-node?
given: '()
(struct tree-node (val left right) #:transparent)
(define (tree-depth tree)
(if (empty-tree? tree) 0
(+ 1 (max (tree-depth (tree-node-left tree))
(tree-depth (tree-node-right tree))))))
For context, this question is follow-up of: Why is it that wrong return for bst scheme
If you don't have to use (struct empty-tree () #:transparent), I would represent an empty tree as an empty list, as I already did in the previous answer. With that, you can rewrite tree-depth this way:
(define (tree-depth tree)
(if (empty? tree) 0
(add1 (max (tree-depth (tree-node-left tree))
(tree-depth (tree-node-right tree))))))
Test:
> (tree-depth (tree-add (tree-add (tree-add (tree-add '() 3) 4) 2) 1))
3
> (tree-depth (tree-add '() 3))
1
If you do want to use the empty-tree type, use that and not the empty list in your tree:
(define (leaf v) (tree-node v (empty-tree) (empty-tree)))
(define a-tree
(tree-node 3 (tree-node 2 (leaf 1) (empty-tree))
(leaf 4)))
> (tree-depth a-tree)
3

Drracket: Create a function that will return a sorted list given a comparer using bubble sort

This is what I have to sort strings:
;create a function that checks if a list of strings is sorted
(define (stringCmpr l)
(if (<= (length l) 1)
true
(and (string<=? (car l) (cadr l))(stringCmpr (cdr l))
)
)
)
;Create a funciton that checks if a list of numbers is sorted
(define (numCmpr l)
(if (<= (length l) 1)
true
(and (<= (car l) (cadr l)) (numCmpr (cdr l))
)
)
)
;create function that checks whether a list containes numbers of
strings checks if the list is sorted
(define (is-sorted? l)
(if (number? (car l))
(numCmpr l)
(stringCmpr l)
)
)
(define (bubble-pass lst)
(cond
((empty? lst) lst)
((= (length lst) 1) lst)
((and (= (length lst) 2) (string>? (first lst) (second lst)))
(list
(second lst) (first lst)))
((and (= (length lst) 2) (string<? (first lst) (second lst)))
lst)
((string>? (first lst) (second lst))
(append
(list (second lst))
(bubble-pass (append (list (first lst)) (rest (rest lst))))
)
)
(else
(append (list (first lst) (second lst)) (bubble-pass (rest
(rest lst))))
)
)
)
(define (string-bubble-sort lst)
(if (is-sorted? lst)
lst
(string-bubble-sort (bubble-pass last))
)
)
This works for sorting strings in order from A-Z
This is what I have so far for the general sort (func represents the comparer: <, > =, string<?, etc):
;create a function that checks if a list of strings is sorted
(define (gen-stringCmpr l func)
(if (<= (length l) 1)
true
(and (func (car l) (cadr l))(gen-stringCmpr (cdr l) func)
)
)
)
;Create a funciton that checks if a list of numbers is sorted
(define (gen-numCmpr l func)
(if (<= (length l) 1)
true
(and (func (car l) (cadr l)) (gen-numCmpr (cdr l) func)
)
)
)
;create funciton that checks whether a list contains numbers or
strings checks if the list is sorted
(define (general-sorted? l func)
(if (number? (car l))
(gen-numCmpr l func)
(gen-stringCmpr l func)
)
)
; Purpose: Create a function that bubble sorts a list given a
; comparison function
;Signature:
; list function-> list
;Examples:
(check-expect (general-bubble-sort (list "B" "A" "C") string<?) (list
"A" "B" "C"))
(check-expect (general-bubble-sort (list "B" "A" "C") string>?) (list
"C" "B" "A"))
(check-expect (general-bubble-sort (list 6 4 5) <) (list 4 5 6))
(check-expect (general-bubble-sort (list 2 3 1) >) (list 3 2 1))
Stub:
(define (general-bubble-sort lst func) '( "spinach")
Template:
Code:
(define (general-bubble-pass lst func)
(cond
((empty? lst) last)
((= (length lst) 1) last)
((and (= (length lst) 2) (equal? (func (first lst) (second lst))
false)) (list (second lst) (first lst)))
((and (= (length lst) 2) (func (first lst) (second lst))) last)
((equal? (func (first lst) (second lst)) false)
(append
(list (second last))
(general-bubble-pass (append (list (first lst)) (rest (rest
lst))) func)
)
)
(else
(append (list (first lst) (second lst)) (general-bubble-pass
(rest (rest lst)) func))
)
)
)
(define (general-bubble-sort lst func)
(if (general-sorted? lst func)
lst
(general-bubble-sort (general-bubble-pass lst func) func)
)
)
You aren't properly using your abstractions here because of overly permissive signatures. Technically you want your final bubble sort to work like this:
; general-bubble-sort: (X) [List-of X] [X X -> Boolean] -> [List-of X]
By constraining the types of what we take in and telling users how they should use it, we eliminate the checking we need to do in general-sorted?. We just know that we have to pass the correct function to it, otherwise it is the users fault for not passing the correct function. You can also abstract more of your code between your two functions. Like this:
(define (general-sorted? l func)
(or (<= (length l) 1) (and (func (car l) (cadr l)) (general-sorted? (cdr l)))))
Your second function has a lot going on in it, lets combine some of the cases and also not use (equal? x boolean). That is bad practice. Instead we should use a boolean expression to get us true when appropriate. We should also make use of accumulators here as it clearly says what piece of data we are keeping track of as we are recurring down:
(define (general-bubble-pass lst func)
(local [(define (general-bubble-pass-acc lst bubble)
(cond
[(empty? lst) (list bubble)]
[(not (func (first lst) bubble)) (cons bubble (general-bubble-pass-acc (rest lst) (first lst)))]
[else (cons (first lst) (general-bubble-pass-acc (rest lst) bubble))]))]
(if (<= (length lst) 1) lst (general-bubble-pass-acc (rest lst) (first lst)))))
Your final bubble sort function doesn't change.

Scheme remove left and right children if they are null

I am trying to write scheme code (DrRaket or MIT) that remove left and right children if they are null.
;;definition of make-tree;;
(define (make-tree entry left right)
(list entry left right))
;;input tree;;
(define tree (8 (5 (2 () ()) (4 () ())) (3 () (10 () ()))))
if I do (print tree) suppose to change the input tree to
;;expected output;;
(8 (5 (2)(4)) (3 () (10)))
;;
(define (print tree)
(cond ((and (null? (cadr tree)) (null? (caddr tree)))
(cons (car tree) '())
(make-tree (car tree) (cadr tree) (caddr tree))
(print tree)
)))
But I get linefeed after attempting (print tree). Could someone help me get the expected output?
In reply to soegaard 33's solution
(define (prune tree)
(cond tree
((list x '() '()) (list x))
((list x left '()) (list (prune left) (list x)))
((list x '() right) (list (list x) (prune right)))
((list x left right) (make-tree x (prune left) (prune right)))))
Output
Welcome to DrRacket, version 6.1.1 [3m].
Language: R5RS; memory limit: 128 MB.
. tree: bad syntax in: tree
>
This solution uses match from Racket.
(define (prune tree)
(match tree
[(list x '() '()) (list x)]
[(list x left '()) (list (prune left) (list x))]
[(list x '() right) (list (list x) (prune right))]
[(list x left right) (make-tree x (prune left) (prune right))]))
The tree has four different shapes.
Each clause handles a different shape.
If you can't use match change it to a cond with four cases.
Update:
(match tree
((list x '() '()) (list x))
...
...)
becomes
(cond
((and (list? tree)
(null? (cadr tree)) ; the second element is '()
(null? (caddr tree))) ; the third element is '()
(list x))
...
...)

Rewrite an item in a list of list

This seems straightforward, but I can't seem to find a solution. I want to replace an item within a list of a list with something, but if that item appears multiple times then you randomly replace one of them, but not both. I want to do this in ISL+.
I created the function flatten which appends all sublists :
(check-expect (flatten '((a b) (c) (d e f g) (h i j)))
(list 'a 'b 'c 'd 'e 'f 'g 'h 'i 'j))
(define (flatten lol)
(foldr append empty lol))
I also made rewrite, which replaces the value at index n with whatever you choose
(check-expect (rewrite '(x x x - x x x x) 3 'x)
(list 'x 'x 'x 'x 'x 'x 'x 'x))
(define (rewrite ls n val)
(cond
[(empty? ls) (error "error")]
[(= n 0) (cons val (rest ls))]
[else (cons (first ls) (rewrite (rest ls) (sub1 n) val))]))
The problem is I don't know how to apply this to a list of list and I also don't know how to randomly replace one of items if it occurs more than once. This is what I have for the final product, but it's probably not the way to go:
(define (fullreplace b)
(local [
;makes a list of nested lists of each index the element occurs
;problem is that it makes a list of nested lists so I can't use flatten either
(define (position ls ele n)
(cond [(empty? ls) 0]
[(equal? ele (first ls)) (list n (position (rest ls) ele (add1 n))) ]
[else (position (rest ls) ele (+ 1 n))]))]
;lol-full? checks if the item occurs in the list of lists at all
(if (lol-full? b) b (rewrite (flatten b)
(position (flatten b) '- 0)
"item replaced"))))
;just used for testing
(define lol2 (list
(list 2 2 2 2)
(list 4 '- 4 '-)
(list '- 8 8 8)
(list 16 '- '- 16)))
(fullreplace lol2) may return this or where any of the other '- are located:
(list
(list 2 2 2 2)
(list 4 '- 4 2)
(list '- 8 8 8)
(list 16 '- '- 16))
I've been working on this awhile so any new insight would go a long way. Thank you
The "random" part is what makes this problem pathological. If you could just replace the first occurrence, it would be easy. But to replace a random occurence, you must first know how many occurrences there are. So before you go replacing stuff, you have to go a-counting:
(define (count/recursive val tree)
(cond ((equal? val tree)
1)
(else (foldl (λ (next-value total)
(cond ((equal? val next-value)
(add1 total))
((list? next-value)
(+ total (count/recursive val next-value)))
(else total))) 0 tree))))
Then you need a function that can replace the nth occurrence of a value:
(define (replace/recursive val replace-with n tree)
(cond ((equal? val tree)
replace-with)
(else
(cdr
(foldl (λ (next-value total/output-tree)
(local ((define total (car total/output-tree))
(define output-tree (cdr total/output-tree)))
(cond ((equal? next-value val)
(cons (add1 total)
(cons (if (= total n) replace-with next-value) output-tree)))
((list? next-value)
(cons (+ total (count/recursive val next-value))
(cons (replace/recursive val replace-with (- n total) next-value)
output-tree)))
(else (cons total (cons next-value output-tree)))))) (cons 0 empty) tree)))))
Finally, you use random to pick the instance you will replace, using count/recursive to limit how high of a number random picks:
(define original '((x x (x y x) a b (((c x z x) x) y x x))))
(replace/recursive 'x '- (random (count/recursive 'x original)) original)
How to replace all occurences of a value with another value:
(define (replace-all needle new-value haystack)
(cond ((equal? needle haystack) new-value)
((pair? haystack)
(cons (replace-all needle new-value (car haystack))
(replace-all needle new-value (cdr haystack))))
(else haystack)))
The only thing to change is to check if the first part constituted a change. If it did you don't do the replace on the other half. Use equal? to compare structure.
It's not random. It will replace the first occurence it finds either by doing car before cdr or cdr before car.

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)))]))

Resources