I wrote the following code that reverses a Scheme list:
(define (my-reverse lst)
(if (null? lst)
'()
(append (my-reverse (cdr lst)) (list (car lst)))))
When I trace this function for the list (list 1 2 3 4 5), Scheme shows this:
>(my-reverse (mcons 1 (mcons 2 (mcons 3 (mcons 4 (mcons 5 '()))))))
> (my-reverse (mcons 2 (mcons 3 (mcons 4 (mcons 5 '())))))
> >(my-reverse (mcons 3 (mcons 4 (mcons 5 '()))))
> > (my-reverse (mcons 4 (mcons 5 '())))
> > >(my-reverse (mcons 5 '()))
> > > (my-reverse '())
< < < '()
< < <(mcons 5 '())
< < (mcons 5 (mcons 4 '()))
< <(mcons 5 (mcons 4 (mcons 3 '())))
< (mcons 5 (mcons 4 (mcons 3 (mcons 2 '()))))
<(mcons 5 (mcons 4 (mcons 3 (mcons 2 (mcons 1 '())))))
What I don't understand, is why at the end 5 is "being appended" to '(), instead of '() being appended to 5? Because in the code there is written (append (my-reverse (cdr lst)) (list (car lst))) and the (my-reverse (cdr lst)) at the end, so (my-reverse (cdr (list 5))) is '()? And the code says (append '() (list 5)?
As you can see in the forward direction in (my-reverse (mcons 5 '())), the way it says "list with one element equal to 5" is (mcons 5 '()). And when the function returns a list of one element, it is once again displayed as (mcons 5 '()) .
Related
for example:
(duplicate 3 (list 1 2 3)) = (list 1 1 1 2 2 2 3 3 3)
i tried this:
(define (duplicate n l)
(cond [(zero? n) empty]
[else (cons l (duplicate (sub1 n) l))]))
but it gives me:
(duplicate 2 (list 1 2)) = (list (list 1 2) (list 1 2))
You are actually half way. What you have created is something that takes one element and a count and makes a list of that many elements.
(duplicate 3 'e) ; ==> (3 3 3)
That means that you can use that:
(duplicate-list 3 l)
; ==> (append (duplicate 3 (car l))
; (duplicate-list 3 (cdr l)))
(define (duplicate n x)
"Repeat x n times."
(cond [(zero? n) empty]
[else (cons x (duplicate (sub1 n) x))]))
(define (mappend fn . lists)
"map but appending the results."
(apply append (apply map fn lists)))
(define (duplicate-list n l)
"duplicate each element in l."
(mappend (lambda (x) (duplicate n x)) l))
Then
(duplicate-list 3 (list 1 2 3))
;; '(1 1 1 2 2 2 3 3 3)
I am trying to use the ability to have multiple "then-expressions" for a conditional in cond but I've yet to be successful in that. The goal is to have a function take in a list and spit out the count.
(define (countInc aList)
(let ((count 0))
(lambda ()
(cond
[(= (length aList) 0) '()]
[(> (second aList) (first aList)) (set! count (+ count 1)) (countInc (rest aList))]
(else (countInc (rest aList)))))))
(check-expect (countInc '(1 2 3 4 5 6)) 5)
To explain, answer is 5 because 2 > 1, 3 > 2, 4 > 3, 5 > 4, and 6 > 5.
Notice that your base case is incorrect: you're returning an empty list, shouldn't we be returning the counter? By the way, your procedure is actually returning a lambda with no arguments, that's not what you want to do.
Also: you should never use length for determining if a list is empty, and in general you should avoid using set! unless strictly necessary - Scheme favors a functional-programming style.
What you want to do can be written without mutating state variables, the trick is to keep track of the previous element while traversing the list - and beware of the many edge cases!
(define (countInc lst)
; edge cases
(if (or (empty? lst) (empty? (rest lst)))
0
; use a named let or a helper procedure
(let loop ((prev (first lst))
(lst (rest lst)))
(cond ((empty? (rest lst)) ; base case
(if (> (first lst) prev) 1 0))
((> (first lst) prev) ; found one, count it
(+ 1 (loop (first lst) (rest lst))))
(else ; skip this one
(loop (first lst) (rest lst)))))))
This works fine even for the edge cases, I've provided tests for them:
(countInc '())
=> 0
(countInc '(1))
=> 0
(countInc '(2 1))
=> 0
(countInc '(1 2))
=> 1
(countInc '(4 1 3 2 5 6))
=> 3
(countInc '(1 2 3 4 5 6))
=> 5
Give a single function to access the element a in the list L.
(define L '(1 2 (a 3 4 5)))
Following the form (define id expr) which binds id to the result of expression I have tried the following:
(define L '(1 2 (a 3 4 5) (car(cdr L))))
cdr accesses the tail of the list, i.e. a 3 4 5, if I am not mistaken, and then I apply car on the tail to access the head of the list, i.e a. However, it is not working on DrRacket IDE.
I think you meant to do this:
(define L '(1 2 (a 3 4 5)))
(car (car (cdr (cdr L))))
=> 'a
Which can also be written as:
(caaddr L)
=> 'a
You included the (car(cdr L)) part inside the list L.
> (define L '(1 2 (a 3 4 5) (car(cdr L))))
> L
(list 1 2 (list 'a 3 4 5) (list 'car (list 'cdr 'L))) ;; oh no
But that still doesn't extract the 'a because you need to access car of the inner list:
(define L '(1 2 (a 3 4 5)))
(car (car (cdr (cdr L))))
;; or (caaddr L)
I want to write a function that search two elements that a given number lies in between; (element1 < num < element2), and their position of first-element in list.
;; check x is between num-1 and num-2
(define (in-between? x num-1 num-2)
(or (and (> num-1 x) (< num-2 x))
(and (> num-2 x) (< num-1 x))))
;; the list elements values are always in ascending order
(define lst '(0 0 0 1 1 1 2 2 2 3 3 4 4 5 5 6 6 6 7))
(define num 4.5)
;; expected-output=> 4.5 lies between element 4 and 5 of lst
;; '(4 5 12) ;; 12 is the position of first-element
;; output is list of 2 elements and the position of first-element
(define (find-interval u lst)
(let* ([x (for/list ([a (drop-right lst 1)]
[b (cdr lst)]
[i (in-naturals)])
(when (in-between? u a b)
(list a b i)))])
(car (filter list? x)))) ; to remove all #<void>
;; => '(4 5 12)
I have to use (car (filter list? x)) to eliminate #<void> outputs in x, which is resulting
'(#<void> #<void> #<void> #<void> #<void> #<void> #<void> #<void> #<void> #<void> #<void> #<void> (4 5 12) #<void> #<void> #<void> #<void> #<void>).
How do I prevent those #<void> in list coming out from for/list in x? It looks like there are unnecessarily longer steps in find-interval function. All the suggestions are welcome and appreciated.
Assuming that the list is always in ascending order, the function can be defined with a simple tail-recursion which is compiled in an iterative way:
(define (find-interval el lst (pos 0))
(cond ((null? lst) '())
((null? (cdr lst)) '())
((>= (car lst) el) '())
((< (car lst) el (cadr lst)) (list (car lst) (cadr lst) pos))
(else (find-interval el (cdr lst) (+ 1 pos)))))
(find-interval 4.5 '(0 0 0 1 1 1 2 2 2 3 3 4 4 5 5 6 6 6 7)) ; => '(4 5 12)
A named let can be used here to test through the list:
(define (find-interval u lst)
(let loop ((idx 1))
(if (= idx (length lst))
#f
(begin (let ((a (list-ref lst (sub1 idx)))
(b (list-ref lst idx)))
(if (in-between? u a b)
(list a b (sub1 idx))
(loop (add1 idx))))))))
It returns #f if such condition does not occur in the list.
Following version will produce a list of lists indicating multiple locations where the condition is satified:
(define (find-interval u lst)
(let loop ((idx 1)
(ol '()))
(if (= idx (length lst))
(reverse ol)
(begin (let ((a (list-ref lst (sub1 idx)))
(b (list-ref lst idx)))
(if (in-between? u a b)
(loop (add1 idx) (cons (list a b (sub1 idx)) ol))
(loop (add1 idx) ol)))))))
(find-interval 4.5 '(0 0 0 1 1 1 2 2 2 3 3 4 4 5 5 6 6 6 7 4 6))
; => '((4 5 12) (7 4 18) (4 6 19))
The input list need not have items in a sorted order in either of above functions.
I'm using R5RS standart of Scheme implementation.
Now imagine you have to find out if an element '(2 3 4) is in a list '(1 2 3 4).
As for the example, and more strictly, you wish:
1. (is-in? '(2 3 4) '(1 2 3 4)) -> #f
2. (is-in? '(2 3 4) '(1 (2 3 4)) -> #t
Question: how to get that kind of behaviour, as in example 1?
Let me explain: when you search throught a list, you could use either car or cdr to get its parts. Now if you recursively go throught the list, you eventually get:
3. (cdr '(1 2 3 4)) -> '(2 3 4)
4. (cdr '(1 (2 3 4)) -> '((2 3 4))
So eventually, we got 2 lists. And you can see here, that sublist '(2 3 4) is contained by both results from 3 and 4.
Please see the contradiction of 3 and 4 with 1 and 2: while '(2 3 4) is not contained in '(1 2 3 4), recursive call of cdr returns '(2 3 4), which is equal to '(2 3 4) - and using equal? function, somewhere inside recursive calls, we eventually get #t for both 1 and 2:
5. (is-in? '(2 3 4) '(1 2 3 4)) -> #t
6. (is-in? '(2 3 4) '(1 (2 3 4)) -> #t
So how to get that kind of behaviour from 1? I want to have a function, which works with all different types of data. Here's my function, which works like 5 and 6 (throught should work as 1 and 2):
(define or (lambda (x y)
(cond ((eq? x y) (eq? x #t))
(#t #t)
)
)
)
(define and (lambda (x y)
(cond ((eq? x y) (eq? x #t))
(#t #f)
)
)
)
(define atom? (lambda (x)
(not (pair? x))
)
)
(define length (lambda (x)
(cond ((eq? x '()) 0)
((atom? x) 1)
(#t (+ (length (car x)) (length (cdr x))))
)
)
)
(define equal? (lambda (x y)
(cond ((and (atom? x) (atom? y)) (eq? x y))
((not (eq? (length x) (length y))) #f)
((not (and (pair? x) (pair? y))) #f)
(#t (and (equal? (car x) (car y)) (equal? (cdr x) (cdr y))))
)
)
)
(define is-in? (lambda (x y)
(cond ((equal? x y) #t)
(#t (cond ((pair? y) (or (is-in? x (car y)) (cond ((eq? (length y) 1) #f)
(#t (is-in? x (cdr y)))
)))
(#t #f)
)
)
)
)
)
Update:
What I want is to have a general function, which can tell you if some object is inside another object. I name entities object to emphasize that the function should work with any input values, simple or complicated like hell.
Example usages:
1. (is-in? 1 '(1 2 3)) ;-> #t
2. (is-in? '(1) '(1 2 3)) ;-> #f
3. (is-in? '(2 . 3) '(1 2 . 3)) ;-> #f
4. (is-in? '(2 . 3) '(1 (2 . 3))) ;-> #t
5. (is-in? '2 '(1 2 . 3)) ;-> #t
6. (is-in? '(2) '(1 2 . 3)) ;-> #f
7. (is-in? '(1 2 (3 4 (5 6 . (7 . 8)) 9) 10 11 (12 . 13)) '(1 (2 3 ((4 ((6 (3 . ((1 2 (3 4 (5 6 . (7 . 8)) 9) 10 11 (12 . 13)))) 3) 4)) 5) 2))) ;-> #t
8. (is-in? '(2 3 4) '((1 (2 3 4)) (1 2 3 4))) ;-> #t
9. (is-in? '(2 3 4) '(1 2 3 4)) ;-> #f
10. (is-in? '(2 3 4) '(1 (2 3 4))) ;-> #t
11. (is-in? '(1) '(1)) ;-> #t
First of all - why are you redefining and, or, equal? and length? those are built-in primitives. Also your definition of atom? is wrong, it should be:
(define (atom? x)
(and (not (pair? x))
(not (null? x))))
I guess you need to implement this from scratch as part of a homework. Let's see how that can be accomplished, fill-in the blanks to get your answer:
(define (is-in? ele lst)
(or <???> ; trivial case: ele == list
(member? ele lst))) ; call helper procedure
(define (member? ele lst)
(cond ((null? lst) ; if the list is empty
<???>) ; then the element is not in the list
((atom? lst) ; if the list is not well-formed
(equal? <???> <???>)) ; then test if ele == list
(else ; otherwise
(or (equal? ele <???>) ; test if ele == the 1st element in the list
(member? ele <???>) ; advance the recursion over the `car`
(member? ele <???>))))) ; advance the recursion over the `cdr`
Notice that the second case in member? is needed because in the examples given there are malformed lists (ending in a non-null value). The above solution will correctly handle all of the examples provided in the question.
(define (is-in? e lst)
(cond ((null? lst) #f) ; if list is empty, we failed
((eq? e (car lst)) #t) ; check 1st element of list
((list? (car lst)) (is-in? e (append (car lst) (cdr lst)))) ; search inside car if it is a list
(#t (is-in? e (cdr lst))))) ; check rest of list
You can replace eq? with something more elaborate to handle other definitions of equality.
Note: this assumes that all sequences are lists; you'll have to tweak it to handle dotted-pairs that are not lists.