DrRacket - update values in binary tree - racket

I'm writing a function which produces a new version of a binary tree bt where each Node whose value is an odd length string, has its value replaced with the string "odd".
For example:
(check-expect (odd-length (make-node 4 "four"
(make-node 7 "seven"
empty
(make-node 2 "two" empty empty))
(make-node 32 "thirty-two" empty empty)))
(make-node 4 "four"
(make-node 7 "odd"
empty
(make-node 2 "odd" empty empty))
(make-node 32 "thirty-two" empty empty))
I've managed to write a function that converts a single value, but I don't know how to make it work for all nodes in the binary tree. Can anyone help? Thanks a lot ><
(define-struct node (key val left right))
(define (change-str bt)
(cond
[(= (remainder (string-length (node-val bt)) 2) 1)
(make-node (node-key bt) "odd" (node-left bt) (node-right bt))]
[(= (remainder (string-length (node-val bt)) 2) 0) bt]))

We can simply define a map over trees and pass change-str as a function over vals.
(define (odd-length tree)
(tree-map identity change-str tree))
(define (change-str str)
(if (odd? (string-length str)) "odd" str))
(define (tree-map func-key func-val tree)
(cond [(empty? tree) tree]
[else (make-node (func-key (node-key tree))
(func-val (node-val tree))
(tree-map func-key func-val (node-left tree))
(tree-map func-key func-val (node-right tree)))]))

Related

Create Python's collections.counter() method in Beginner Racket

The goal is to create a function that accepts a list of symbols and produces a list of key value pairs that count how many times each symbol in list appears. eg:
(counter (list 't 't 'c 'a)) -> (list (list 't 2) (list 'c 1) (list 'a 1))
The function must be completed with recursion
I've only gotten as far as to create a list of key value pairs that treat duplicates as standalone values:
(define val 0)
(define (counter los)
(cond
[(empty? los) empty]
[else (cons (list (first los) (add1 val))
(counter (rest los)))]))
(counter (list 't 't 'c 'a)) -> (list (list 't) (list 't) (list 'c 1) (list 'a 1))
It has been a very long time since I used BSL but I believe these operations are all present. There may be a cleaner way of doing this but I will leave it up to you to check the documentation and simplify it if possible
(define (counter los) (counter-helper los empty))
(define (counter-helper los lists)
(cond
[(empty? los) lists]
[else (if (list? (assq (first los) lists))
(counter-helper
(rest los)
(cons (list (first los) (add1 (second (assq (first los) lists))))
(remove (assq (first los) lists) lists)))
(counter-helper (rest los) (cons (list (first los) 1) lists)))]))
the if statement checks if there is already an entry in our list of lists for that key, it returns the pair if yes, false otherwise.
If the result is false we just append a new pair with value 1 and recur.
If it already exists, we construct a new pair from the previous one, with the same key, but the value incremented and append this new pair to our list of lists - the previous pair removed

Racket List Questio

Does anyone know how to return a number of specific elements in a list?
Example: given
(list 'a 'a 'a 'a 'a 'b 'b 'b)
Returns the numbers of 'a: 5
numbers of 'b: 3
You count them. You make a procedure that takes a list and what you want to search for and you iterate that list while keeping a count and when you reach the end you return that value.
A skeleton for a simple recursive solution:
(define (count-element element lst)
(define (helper lst count)
(cond ((empty? lst) count)
((equal? element <first element>) <recurse whith cdr and increasing count>)
(else <recurse with cdr>)))
(helper lst 0))
Or you can use foldl
(define (count-element element lst)
(foldl (lambda (e count)
(if <e is the same as element>
<return 1 more than count>
<return count>))
0
lst))
There are probably 10 more ways I could do it, but the first is the most educational and the second the most common way I would do it.
Some tests:
(define test '(a a a a a b b b))
(count-element 'b '()) ; ==> 0
(count-element 'e test) ; ==> 0
(count-element 'a test) ; ==> 5
(count-element 'b test) ; ==> 3
I somewhat managed to find the answer, so here's the function definition:
(define (number-of s L)
(cond
[(empty? L) 0]
[else (cond [(eq? s (first L)) (+ 1 (number-of s (rest L)))]
[else (number-of s (rest L))])]))

Print values, not types (Racket)

When I print in Racket, only the type is printed of structures, not the value. (I'm working in DrRacket, in the interactions area.)
For example, I have a tree structure:
#lang racket
(define-struct node [name left right])
An example could be:
(define SALLY (make-node 'sally BOBBY SUSIE))
(define BOBBY (make-node 'bobby NONE NONE))
(define SUSIE (make-node 'susie NONE NONE))
What I see:
> (print SALLY)
#<node>
What I want to see:
> (print SALLY)
(make-node 'sally (make-node 'bobby NONE NONE)
(make-node 'susie NONE NONE))
How can I see the value and not the type?
Use #:transparent keyword:
(define-struct node [name left right] #:transparent)
> (define-struct node [name left right] #:transparent)
> (define NONE '())
> (define BOBBY (make-node 'bobby NONE NONE))
> (define SUSIE (make-node 'susie NONE NONE))
> (define SALLY (make-node 'sally BOBBY SUSIE))
> (print SALLY)
(node 'sally (node 'bobby '() '()) (node 'susie '() '()))
NB: Today struct is preferred over define-struct so I've written the code with struct.
It doesn't really print the type but it's the default representation of the object. There are two options you can do:
1. Use #:transparent keyword.
(struct node [name left right] #:transparent)
(define root (node 'd
(node 'b (node 'a '() '())
(node 'c '() '()))
(node 'f (node 'e '() '())
(node 'g '() '()))))
root ; ==>
; (node 'd
; (node 'b (node 'a '() '())
; (node 'c '() '()))
; (node 'f (node 'e '() '())
; (node 'g '() '()))))
Notice how they look like the construction?
1. Add a writer for the object
(struct node [name left right]
#:methods gen:custom-write
[;; needs to be named write-proc
(define (write-proc x port mode)
((if (eq? mode #t) write display) (fancy-writer x 0) port))
;; helper used by write-proc
(define (fancy-writer x ident)
(if (null? x)
""
(let ([new-ident (+ 5 ident)])
(string-append (fancy-writer (node-left x) new-ident)
(string-append (make-string ident #\space)
(symbol->string (node-name x))
"\n")
(fancy-writer (node-right x) new-ident)))))])
root ; ==>
; a
; b
; c
; d
; e
; f
; g

(fixing a code for) racket-- deleting a node from a tree

So I'm currently stuck in the intermediate level of racket, and have looked at various codes, but most of them I can't figure out
I'm trying to delete a node from a binary search tree
So, I've so far come up with this, which includes an empty node and the first and final node in the wrong order
(define-struct node (key value left right))
(define (delete bst k)
(local [(define empty-l (empty? (node-left bst)))
(define empty-r (empty? (node-right bst)))
(define full-l (not empty-l))
(define full-r (not empty-r))]
(local [(define (replace bst)
;;takes node and takes it away, finding the next part that should take over its spot
(cond
[(empty? bst) empty]
[(and empty-l empty-r) empty]
[(and empty-l full-r) (node-right bst)]
[(and full-l empty-r) (node-left bst)]
[(and full-l full-r) (make-node
(if (**empty? (node-right bst)) "MAKE_THIS_KEY_GO_AWAY"** (node-key (node-right bst)))
(if (**empty? (node-right bst)) "MAKE_THIS_VALUE_GO_AWAY"** (node-value (node-right bst)))
;(node-value (node-right bst))
(node-left bst)
(replace (node-right bst)))]))]
;(local ((define (find k bst)
;;if finds k, puts it through replace to replace it
(cond
[(empty? bst) empty]
[(= k (node-key bst)) (replace bst)]
[(< k (node-key bst)) (make-node (node-key bst)
(node-value bst)
(delete k (node-left bst))
(node-right bst))]
[else (make-node (node-key bst)
(node-value bst)
(node-left bst)
(delete k (node-right bst)))]))))
;; Example binary search tree for check-expect
(define t (make-node 5 "" (make-node 3 "" (make-node 2 "" (make-node 1 "" empty empty)
empty)
(make-node 4 "" empty empty))
(make-node 7 "" (make-node 6 "" empty empty) empty)))
(check-expect (delete t 5)
(**make-node 6 ""** (make-node 3 "" (make-node 2 "" (make-node 1 "" empty empty)
empty)
(make-node 4 "" empty empty))
(**make-node 7 ""** empty empty)))
;;What I actually get
(**make-node
7
""**
(make-node
3
""
(make-node
2
""
(make-node 1 "" empty empty)
empty)
(make-node 4 "" empty empty))
(**make-node
"MAKE_THIS_KEY_GO_AWAY"
"MAKE_THIS_VALUE_GO_AWAY"**
(**make-node 6 ""** empty empty)
empty))
The (full-l full-r) case is all messed up. To handle that case, you need to pick either what Wikipedia calls the "in-order predecessor" or the "in-order successor" of the instance of bst being handled by replace, then delete that key from replace's bst and make it be the replacement. These functions can be used to find the in-order predecessor/successor:
(define (in-order-predecessor tree)
(right-bottom (node-left tree)))
(define (in-order-successor tree)
(left-bottom (node-right tree)))
(define (left-bottom tree)
(if (empty? (node-left tree))
tree
(left-bottom (node-left tree))))
(define (right-bottom tree)
(if (empty? (node-right tree))
tree
(right-bottom (node-right tree))))
So you'd do something like this:
[(and full-l full-r)
(local [(define successor (in-order-successor bst))
(define old-right (node-right bst))
(define new-right (delete old-right (node-key successor)))]
(make-node (node-key successor) (node-value successor)
(node-left bst) new-right))]
Since this version of replace would no longer be recursive, it doesn't need to receive bst as an argument.
Also, you're getting the argument order of delete mixed up. You defined it as (delete node k) but in two places you call it as (delete k node).

LISP Lists sublist

function that only deletes the first element of each sublist in the list. For example,
Test 1:
List is (10 (1 2 3) (90 100) 122 156)
Output should be: (10 (2 3) (100) 122 156)
I know how to delete an element from the list but i don't know which function is used to delete element from the sublist
(defun butfirst (lst)
(mapcar
(lambda (e) (if (consp e) (cdr e) e))
lst))
(butfirst '(10 (1 2 3) (90 100) 122 156))
=> (10 (2 3) (100) 122 156)
yet another offer: without iteration, with a recursive algorithm.
(defun butfirst (lst)
(cond
((null lst) '())
((consp (car lst))
(cons (cdr (car lst))
(butfirst (cdr lst))))
(t (cons (car lst)
(butfirst (cdr lst))))))