Assume that my "map-diff" function works properly for the following code. I am wondering how to take an arithmetic parse tree and output it in preorder notation. I want to be able to use my "map-diff" function inside my "preorder" function, but I can't figure out how to go about doing this. Are my base cases here correct?
(define (make-tree value left right) (list value left right))
(define (value tree) (car tree))
(define (left tree) (cadr tree))
(define (right tree) (caddr tree))
(define (prepare x)
(cond ((number? x) (number->string x))
((char? x) (string x))))
(define x
(map-diff (lambda (x) (prepare x))
(list #\+
(list #\*
(list 3 '() '())
(list 9 '() '()))
(list #\+
(list #\/ (list 5 '() '()) '())
(list 4 '() '())))))
(define (preorder T)
(cond ((null? T) "")
((eq? (value T) "+")
(cons (value T) (cons (preorder (left T)) (preorder (right T)))))
((eq? (value T) "*")
(cons (value T) (cons (preorder (left T)) (preorder (right T)))))
((eq? (value T) "-")
(cons "-" (preorder (left T))))
((eq? (value T) "/")
(cons "/" (preorder (left T))))
(else (value T))))
(preorder x)
First , don't mix your ADT and primative types together. If you define an ADT stick with it thoughout the program. X should be defined in terms of make-tree rather than list). And make-tree rather than cons in preorder. The way you have it now your going to get a dotted list as output rather than a nice proper list form.
I'm not sure what your trying to do with prepare, casting things to strings to parse them is fairly unusual, considering lisps dynamic typing.
Anyways here is one possibility
(define (preorder T)
(let ((top (prepare (value T))))
(cond ((null? T) "")
((eq? top "+")
(cons top (cons (preorder (left T)) (preorder (right T)))))
((eq? top "*")
(cons top (cons (preorder (left T)) (preorder (right T)))))
((eq? top "-")
(cons "-" (preorder (left T))))
((eq? top "/")
(cons "/" (preorder (left T))))
(else top)))
;; helper
(define (list-ref-at n)
(lambda (l) (list-ref l n)))
;; node data type
(define (make-node value left right)
`(NODE ,value ,left ,right))
(define node-value (list-ref-at 1))
(define node-left (list-ref-at 2))
(define node-right (list-ref-at 3))
;; leaf data type (as special node)
(define (make-leaf value)
(make-node value '() '()))
(define (node-is-leaf? node)
(and (null? (node-left node))
(null? (node-right node))))
;; convert to list
(define (node->preorder-list node)
(if (node-is-leaf? node)
(node-value node)
(let ((v (node-value node))
(l (node-left node))
(r (node-right node)))
(assert (not (null? l)))
(if (null? r)
(list v (node->preorder-list l)) ; unop
(list v (node->preorder-list l) (node->preorder-list r)))))) ;binop
;; test
> (define x (make-node '* (make-node '+ (make-leaf 1) (make-leaf 2)) (make-leaf 10))
> (node->preorder-list x)
(* (+ 1 2) 10)
> (set! x (make-node '- x '()))
> (node->preorder-list x)
(- (* (+ 1 2) 10))
Related
Getting an error for my binary search tree that I created in scheme.
$gosh main.sc
*** ERROR: list required, but got 5
Stack Trace:
_______________________________________
This is my code. I think the error has to do with how I am calling the functions, but I am not sure what exactly is wrong. I am calling the insert function with the two required parameters: tree, and a value of 5.
(define (member? t v)
(cond
((null? t)
#f
)
((< node (car t))
(member? (cadr t) v))
((> node (car t))
(member? (caddr t) v))
(else
#t
)
)
)
(define (insert t v)
(cond
((null? t)
(list v '() '())
)
((< v (car t))
(list (car t) (insert (cadr t) v) (caddr t))
)
((>= v (car t))
(list (car t) (cadr t) (insert (caddr t) v))
)
(else
t
)
)
)
(define (fold func val lst)
(if (null? lst) val (fold func (func val (car lst)) (cdr lst))))
(define (build lst)
(fold (lambda (t v) (insert t v)) '() lst))
(define t (list 10 '() '()))
(insert t 5)
display (member t 5)
display t
You care calling (member t 5) which is the same as (member '(10 '() '()) 5). Now member is not the same as your defined member? since it has a different name. member is the core library that looks like this:
(define (member obj lst)
(cond ((null? lst) #f)
((equal? obj (car lst)) lst)
(else (member obj (cdr lst)))))
Your member? has the two parameters swapped so when you miswrote the name and used the report version member 5 is not null, then it will do (car 5) and that will fail miserably. The error message that 5 is not of the required type list is pretty decent. It might spell the beans that it was member that failed though.
Another thing. If you replace the call to member with a call to member? you hit more problems. You use a variable node that is not defined anywhere.
The indentation and placing of parentheses is not goo lisp style. Your code should be written like this:
;; node doesn't exist in OPs code, but my implementation doesn't like member? without it
(define node 5)
;; possible typo by using the variable node ?
(define (member? t v)
(cond
((null? t)
#f)
((< node (car t))
(member? (cadr t) v))
((> node (car t))
(member? (caddr t) v))
(else
#t)))
(define (insert t v)
(cond
((null? t)
(list v '() '()))
((< v (car t))
(list (car t) (insert (cadr t) v) (caddr t)))
((>= v (car t))
(list (car t) (cadr t) (insert (caddr t) v)))
(else
t)))
(define (fold func val lst)
(if (null? lst) val (fold func (func val (car lst)) (cdr lst))))
(define (build lst)
(fold (lambda (t v) (insert t v)) '() lst))
(define t (list 10 '() '()))
(insert t 5)
;; NB doesn't call a procedure, just evaluates it.
display
;; Here the arguments are the wrong order and you don't use memeber?
(member t 5)
;; NB doesn't call a procedure, just evaluates it.
display
t
I have to solve nest task using language Racket. By given list I have to create new list holding only elements that division by 10 has no leftover.
My code so far:
(define (brel x sp)
(cond ((null? sp) 0)
(( = (remainder (car sp) 10) 0) (car sp))
(else (brel x (cdr sp)))))
(define (spbr L)
(define (f l1)
(if (null? l1) '()
(cons (brel (car l1) L) (f (cdr l1)))))
(f L))
(spbr (list 50 5 3))
Give code currently count every repeats of elements in first list and add them in new one. What must I change to make it works?
You don't need a helper procedure, just build a new list with only the items that meet the condition:
(define (spbr L)
(cond ((null? L) '())
((= (remainder (car L) 10) 0)
(cons (car L) (spbr (cdr L))))
(else
(spbr (cdr L)))))
Using the filter procedure would be more idiomatic:
(define (spbr L)
(filter (lambda (e) (zero? (remainder e 10)))
L))
Either way, it works as expected:
(spbr '(50 5 3 70))
=> '(50 70)
(define (nth n lst)
(if (= n 1)
(car lst)
(nth (- n 1)
(cdr lst) )))
is an unsafe partial function, n may go out of range. An error can be helpful,
(define (nth n lst)
(if (null? lst)
(error "`nth` out of range")
(if (= n 1)
(car lst)
(nth (- n 1)
(cdr lst) ))))
But what would a robust Scheme analogue to Haskell's Maybe data type look like?
data Maybe a = Nothing | Just a
nth :: Int -> [a] -> Maybe a
nth _ [] = Nothing
nth 1 (x : _) = Just x
nth n (_ : xs) = nth (n - 1) xs
Is just returning '() adequate?
(define (nth n lst)
(if (null? lst) '()
(if (= n 1)
(car lst)
(nth (- n 1)
(cdr lst) ))))
It's easy to break your attempt. Just create a list that contains an empty list:
(define lst '((1 2) () (3 4)))
(nth 2 lst)
-> ()
(nth 100 lst)
-> ()
The key point that you're missing is that Haskell's Maybe doesn't simply return a bare value when it exists, it wraps that value. As you said, Haskell defines Maybe like so:
data Maybe a = Nothing | Just a
NOT like this:
data Maybe a = Nothing | a
The latter is the equivalent of what you're doing.
To get most of the way to a proper Maybe, you can return an empty list if the element does not exist, as you were, but also wrap the return value in another list if the element does exist:
(define (nth n lst)
(if (null? lst) '()
(if (= n 1)
(list (car lst)) ; This is the element, wrap it before returning.
(nth (- n 1)
(cdr lst) ))))
This way, your result will be either an empty list, meaning the element did not exist, or a list with only one element: the element you asked for. Reusing that same list from above, we can distinguish between the empty list and a non-existant element:
(define lst '((1 2) () (3 4)))
(nth 2 lst)
-> (())
(nth 100 lst)
-> ()
Another way to signal, that no matching element was found, would be to use multiple return values:
(define (nth n ls)
(cond
((null? ls) (values #f #f))
((= n 1) (values (car ls) #t))
(else (nth (- n 1) ls))))
This comes at the expense of being a little bit cumbersome for the users of this function, since they now have to do a
(call-with-values (lambda () (nth some-n some-list))
(lambda (element found?)
... whatever ...))
but that can be alleviated by using some careful macrology. R7RS specifies the let-values syntax.
(let-values (((element found?) (nth some-n some-list)))
... whatever ...)
There are several ways to do this.
The direct equivalent would be to mimic the Miranda version:
#!r6rs
(library (sylwester maybe)
(export maybe nothing maybe? nothing?)
(import (rnrs base))
;; private tag
(define tag-maybe (list 'maybe))
;; exported tag and features
(define nothing (list 'nothing))
(define (maybe? v)
(and (pair? v)
(eq? tag-maybe (car v))))
(define (nothing? v)
(and (maybe? v)
(eq? nothing (cdr v))))
(define (maybe v)
(cons tag-maybe v)))
How to use it:
#!r6rs
(import (rnrs) (sylwester maybe))
(define (nth n lst)
(cond ((null? lst) (maybe nothing))
((zero? n) (maybe (car lst)))
(else (nth (- n 1) (cdr lst)))))
(nothing? (nth 2 '()))
; ==> #t
Exceptions
(define (nth n lst)
(cond ((null? lst) (raise 'nth-nothing))
((zero? n) (car lst))
(else (nth (- n 1) (cdr lst)))))
(guard (ex
((eq? ex 'nth-nothing)
"nothing-value"))
(nth 1 '())) ; ==> "nothing-value"
Default value:
(define (nth n lst nothing)
(cond ((null? lst) nothing)
((zero? n) (car lst))
(else (nth (- n 1) (cdr lst)))))
(nth 1 '() '())
; ==> '()
Deault value derived from procedure
(define (nth index lst pnothing)
(cond ((null? lst) (pnothing))
((zero? n) (car lst))
(else (nth (- n 1) (cdr lst)))))
(nth 1 '() (lambda _ "list too short"))
; ==> "list too short"
Combination of exception and default procedure
Racket, a Scheme decent, often has a default value option that defaults to an exception or a procedure thunk. It's possible to mimic that behavior:
(define (handle signal rest)
(if (and (not (null? rest))
(procedure? (car rest)))
((car rest))
(raise signal)))
(define (nth n lst . nothing)
(cond ((null? lst) (handle 'nth-nothing nothing))
((zero? n) (car lst))
(else (nth (- n 1) (cdr lst)))))
(nth 1 '() (lambda () 5)) ; ==> 5
(nth 1 '()) ; exception signalled
As a non-lisper I really can't say how idiomatic this is, but you could return the Church encoding of an option type:
(define (nth n ls)
(cond
((null? ls) (lambda (default f) default))
((= n 1) (lambda (default f) (f (car ls))))
(else (nth (- n 1) ls))))
But that's about as complicated to use as #Dirk's proposal. I'd personally prefer to just add a default argument to nth itself.
I wrote 90% of a tree-map function in scheme, but I encountered a major problem that I am having trouble with. When I test my code with binary tree, all but the first node gets mapped properly. The first node drops out, and I can't seem to think of a way around this. Any advice here as would be appreciated.
(define (value tree)
(car tree))
(define (left tree)
(car (cdr tree)))
(define (right tree)
(car (cdr (cdr tree))))
(define (tree-map f T)
(cond ((null? T) '())
((and (null? (right T))(null? (left T))) '())
((and (null? (right T))(not (null? (left T))))
(make-tree (f (value(left T)))
(tree-map f (left T))
(right T)))
((and (null? (left T))(not (null? (right T))))
(make-tree (f (value(right T)))
(left T)
(tree-map f (right T))
))))
This code is really convoluted. First I don't see an else statement, and a pretty big case drop (if both branches are not null tress). Second why are you worrying if the left or right is null when you have a case already for null trees?
(define (tree-map f T)
(cond ((null? T) '())
(else (make-tree (f (value T))
(tree-map f (left T))
(tree-map f (right T))))))
Being a human compiler is no fun. All you've don with you leaf, empty-left, and empty-right cases is rewrite the same code, but manually drop in the '() where appropriate instead of relying on the function to do it for you.
It seems that there are a couple of errors:
If a leaf node is found, you aren't applying the function to that node
The case where a node has both subtrees is missing
The part where the function is applied is wrong
Try this with one of your samples, the question doesn't include all the necessary code to test it myself:
(define (tree-map f T)
; empty tree
(cond ((null? T)
'())
; leaf node
((and (null? (right T)) (null? (left T)))
(make-tree (f (value T)) '() '()))
; empty right subtree
((and (null? (right T)) (not (null? (left T))))
(make-tree (f (value T))
(tree-map f (left T))
'()))
; empty left subtree
((and (null? (left T)) (not (null? (right T))))
(make-tree (f (value T))
'()
(tree-map f (right T))))
; both subtrees are present
(else
(make-tree (f (value T))
(tree-map f (left T))
(tree-map f (right T))))))
how to design a function content which
inputs a single list of atoms lat and which returns
the content of lat.Thus the content of '(a b c a b c d d) is '(a b c d).
The procedure content below should get you what you need.
(define (work x y)
(if (null? (cdr x))
(if (in? (car x) y)
y
(cons (car x) y))
(if (in? (car x) y)
(work (cdr x) y)
(work (cdr x) (cons (car x) y)))))
(define (in? x y)
(if (null? y)
#f
(if (equal? x (car y))
#t
(in? x (cdr y)))))
(define (content x) (work x (list)))
The procedure content accepts a list as a parameter. It sends the list to another procedure called work. This procedure processes the list and adds the items in the list to a new list (if they are not already in the new list). The work procedure makes use of yet another procedure called in, which checks to see if an item is a member of a list.
My solution essentially divides your problem into two sub-problems and makes use of procedures which operate at a lower level of abstraction than your original problem.
Hope that helps.
It is PLT Scheme solution:
(define (is_exists list element)
(cond
[(empty? list) false]
[else
(cond
[(= (first list) element) true]
[else (is_exists (rest list) element)])]))
(define (unique list target)
(cond
[(empty? list) target]
[else
(cond
[(is_exists target (first list)) (unique (rest list) target)]
[else (unique (rest list) (cons (first list) target))])]))
(define (create_unique list)
(unique list empty))
Check it:
> (define my_list (cons '1 (cons '2 (cons '3 (cons '2 (cons '1 empty))))))
> my_list
(list 1 2 3 2 1)
> (create_unique my_list)
(list 3 2 1)
How about little schemer style,
(define (rember-all a lat)
(cond
((null? lat) '())
((eq? a (car lat)) (rember-all a (cdr lat)))
(else (cons (car lat) (rember-all a (cdr lat))))))
(define (content lat)
(cond
((null? lat) '())
(else (cons (car lat)
(content (rember-all (car lat) (cdr lat)))))))
Start from a procedure that simply creates a copy of the passed-in list (very easy to do):
(define (unique-elements seq)
(define (loop ans rest)
(cond ((null? rest) ans)
(else
(loop (cons (car rest) ans)
(cdr rest)))))
(loop '() seq))
To ensure that the output list's elements are unique, we should skip the CONS if the head of REST is already a member of ANS. So we add another condition to do just that:
;;; Create list containing elements of SEQ, discarding duplicates.
(define (unique-elements seq)
(define (loop ans rest)
(cond ((null? rest) ans)
((member (car rest) ans) ; *new*
(loop ans (cdr rest))) ; *new*
(else
(loop (cons (car rest) ans)
(cdr rest)))))
(loop '() seq))
The following function takes in a list and returns a new list with only the unique inputs of it's argument using recursion:
(defun uniq (list)
(labels ((next (lst new)
(if (null lst)
new
(if (member (car lst) new)
(next (cdr lst) new)
(next (cdr lst) (cons (car lst) new))))))
(next list ())))
As was mentioned in the comments, common lisp already has this function:
(defun uniq (list)
(remove-duplicates list))
(define (remove-duplicates aloc)
(cond
((empty? aloc) '())
(else (cons (first aloc)
(remove-duplicates
(filter (lambda (x)
(cond
((eq? x (first aloc)) #f)
(else #t)))
(rest aloc)))))))