I'm reading this book:
http://www.shido.info/lisp/scheme3_e.html
I'm stuck on this exercise:
(car '((1 2 3) (4 5 6)))
The thing is, from my understanding, I must understand how do we get ((1 2 3) (4 5 6)) to get (car '((1 2 3) (4 5 6))) because car evaluates the first address.
I tried a few times but cannot get the exact "string" (I don't even know how to call them):
(cons (cons 1 (cons 2 (cons 3 '()))) (cons 4 (cons 5 (cons 6 '()))))
gives me
{{1 2 3} 4 5 6}
(cons (cons (cons 1 (cons 2 (cons 3 '()))) '()) (cons 4 (cons 5 (cons 6 '()))))
gives me
{{{1 2 3}} 4 5 6}
(cons (cons (cons 1 (cons 2 (cons 3 '()))) '()) (cons (cons 4 (cons 5 (cons 6 '()))) '()))
gives me
{{{1 2 3}} {4 5 6}}
At least I'm getting brackets for both parts...
The thing is, if each time I call car to get the first address, I need to formulate the result in my head to see the other side of the mountain, this seems to be an extremely difficult language to me...so I hope I'm wrong.
'((1 2 3) (4 5 6)) is (cons (cons 1 (cons 2 (cons 3 '()))) (cons (cons 4 (cons 5 (cons 6 '()))) '()))
> (cons (cons 1 (cons 2 (cons 3 '()))) (cons (cons 4 (cons 5 (cons 6 '()))) '()))
'((1 2 3) (4 5 6))
If we replace the inner lists with symbols because their value does not matter we get:
(car '((1 2 3) (4 5 6)))
(car '(X Y))
(car (cons 'X (cons 'Y '())))
Which by the reduction (car (cons A B)) => A produces 'X so the result is (cons 1 (cons 2 (cons 3 '()))) or '(1 2 3)
Related
I would like to ask you for help to solve my task with printing of result of code below. Input is: (run-length-encode '(1 1 2 2 3 3 4 4 a a b b)) and it returns ((2 . 1) (2 . 2) (2 . 3) (2 . 4)) but i would like to have output like (2 1 2 2 2 3 2 4 2 a 1 b). What i am doing wrong?
(define (run-length-encode lst)
(define (rle val-lst cur-val cur-cnt acc)
(if (pair? val-lst)
(let ((new-val (car val-lst)))
(if (eq? new-val cur-val)
(rle (cdr val-lst) cur-val (+ cur-cnt 1) acc)
(rle (cdr val-lst) new-val 1 (cons (cons cur-cnt cur-val) acc))))
(cons (cons cur-cnt cur-val) acc)))
(if (pair? lst)
(reverse (rle (cdr lst) (car lst) 1 '()))
'()))
Thank you for help,
Jan
Deos anyone know, how I can make this funktion recursive by inserting the function somewhere? I am not allowed to use implemented functions for lists except append, make-pair(list) and reverse.
(: split-list ((list-of %a) -> (tuple-of (list-of %a) (list-of %a))))
(check-expect (split-list (list 1 2)) (make-tuple (list 1) (list 2)))
(check-expect (split-list (list 1 2 3 4)) (make-tuple (list 1 3) (list 2 4)))
(check-expect (split-list (list 1 2 3)) (make-tuple (list 1 3) (list 2)))
(check-expect (split-list (list 1 2 3 4 5)) (make-tuple (list 1 3 5) (list 2 4)))
(check-expect (split-list (list 1 2 3 4 5 6)) (make-tuple (list 1 3 5) (list 2 4 6)))
(define split-list
(lambda (x)
(match x
(empty empty)
((make-pair a empty) (make-tuple a empty))
((make-pair a (make-pair b empty)) (make-tuple (list a) (list b)))
((make-pair a (make-pair b c)) (make-tuple (list a (first c)) (list b (first(rest c))))))))
Code for make-tuple:
(define-record-procedures-parametric tuple tuple-of
make-tuple
tuple?
(first-tuple
rest-tuple))
Here's a way you can fix it using match and a named let, seen below as loop.
(define (split xs)
(let loop ((xs xs) ;; the list, initialized with our input
(l empty) ;; "left" accumulator, initialized with an empty list
(r empty)) ;; "right" accumulator, initialized with an empty list
(match xs
((list a b rest ...) ;; at least two elements
(loop rest
(cons a l)
(cons b r)))
((cons a empty) ;; one element
(loop empty
(cons a l)
r))
(else ;; zero elements
(list (reverse l)
(reverse r))))))
Above we use a loop to build up left and right lists then we use reverse to return the final answer. We can avoid having to reverse the answer if we build the answer in reverse order! The technique used here is called continuation passing style.
(define (split xs (then list))
(match xs
((list a b rest ...) ;; at least two elements
(split rest
(λ (l r)
(then (cons a l)
(cons b r)))))
((cons a empty) ;; only one element
(then (list a) empty))
(else ;; zero elements
(then empty empty))))
Both implementations perform to specification.
(split '())
;; => '(() ())
(split '(1))
;; => '((1) ())
(split '(1 2 3 4 5 6 7))
;; => '((1 3 5 7) (2 4 6))
Grouping the result in a list is an intuitive default, but it's probable that you plan to do something with the separate parts anyway
(define my-list '(1 2 3 4 5 6 7))
(let* ((result (split my-list)) ;; split the list into parts
(l (car result)) ;; get the "left" part
(r (cadr result))) ;; get the "right" part
(printf "odds: ~a, evens: ~a~n" l r))
;; odds: (1 3 5 7), evens: (2 4 6)
Above, continuation passing style gives us unique control over the returned result. The continuation is configurable at the call site, using a second parameter.
(split '(1 2 3 4 5 6 7) list) ;; same as default
;; '((1 3 5 7) (2 4 6))
(split '(1 2 3 4 5 6 7) cons)
;; '((1 3 5 7) 2 4 6)
(split '(1 2 3 4 5 6 7)
(λ (l r)
(printf "odds: ~a, evens: ~a~n" l r)))
;; odds: (1 3 5 7), evens: (2 4 6)
(split '(1 2 3 4 5 6 7)
(curry printf "odds: ~a, evens: ~a~n"))
;; odds: (1 3 5 7), evens: (2 4 6)
Oscar's answer using an auxiliary helper function or the first implementation in this post using loop are practical and idiomatic programs. Continuation passing style is a nice academic exercise, but I only demonstrated it here because it shows how to step around two complex tasks:
building up an output list without having to reverse it
returning multiple values
I don't have access to the definitions of make-pair and make-tuple that you're using. I can think of a recursive algorithm in terms of Scheme lists, it should be easy to adapt this to your requirements, just use make-tuple in place of list, make-pair in place of cons and make the necessary adjustments:
(define (split lst l1 l2)
(cond ((empty? lst) ; end of list with even number of elements
(list (reverse l1) (reverse l2))) ; return solution
((empty? (rest lst)) ; end of list with odd number of elements
(list (reverse (cons (first lst) l1)) (reverse l2))) ; return solution
(else ; advance two elements at a time, build two separate lists
(split (rest (rest lst)) (cons (first lst) l1) (cons (second lst) l2)))))
(define (split-list lst)
; call helper procedure with initial values
(split lst '() '()))
For example:
(split-list '(1 2))
=> '((1) (2))
(split-list '(1 2 3 4))
=> '((1 3) (2 4))
(split-list '(1 2 3))
=> '((1 3) (2))
(split-list '(1 2 3 4 5))
=> '((1 3 5) (2 4))
(split-list '(1 2 3 4 5 6))
=> '((1 3 5) (2 4 6))
split is kind of a de-interleave function. In many other languages, split names functions which create sublists/subsequences of a list/sequence which preserve the actual order. That is why I don't like to name this function split, because it changes the order of elements in some way.
Tail-call-rescursive solution
(define de-interleave (l (acc '(() ())))
(cond ((null? l) (map reverse acc)) ; reverse each inner list
((= (length l) 1)
(de-interleave '() (list (cons (first l) (first acc))
(second acc))))
(else
(de-interleave (cddr l) (list (cons (first l) (first acc))
(cons (second l) (second acc)))))))
You seem to be using the module deinprogramm/DMdA-vanilla.
The simplest way is to match the current state of the list and call it again with the rest:
(define split-list
(lambda (x)
(match x
;the result should always be a tuple
(empty (make-tuple empty empty))
((list a) (make-tuple (list a) empty))
((list a b) (make-tuple (list a) (list b)))
;call split-list with the remaining elements, then insert the first two elements to each list in the tuple
((make-pair a (make-pair b c))
((lambda (t)
(make-tuple (make-pair a (first-tuple t))
(make-pair b (rest-tuple t))))
(split-list c))))))
I have a question on a homework assignment that is as follows:
I have the first part (double-list-elements) complete
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
but I honestly have absolutely no idea how to proceed with double-list-elements-one. Any pointers would be greatly appreciated.
Close But No Cigar:
(define (double-list-elements s)
(if (null? s)
'()
(cons (* 2 (car s))
(double-list-elements (cdr s)))))
(define (custom-map proc lst)
(if (null? lst)
'()
(cons (proc lst)
(custom-map proc (cdr lst)))))
(define (double-list-elements-one func s)
(custom-map double-list-elements s))
(double-list-elements-one double-list-elements '(1 2 3 4 5 6))
Output = (list (list 2 4 6 8 10 12) (list 4 6 8 10 12) (list 6 8 10 12) (list 8 10 12) (list 10 12) (list 12))
I need to pass double-list-elements to double-list-elements-one as a parameter as well as the list.
You just have to write your own map, it's very very similar to what you already have, simply pass the part that changes as a procedure parameter, and invoke it on the right place:
(define (mymap proc lst)
(if (null? lst)
'()
(cons <invoke proc on current element>
(mymap proc (cdr lst)))))
(define (double-list-elements-one s)
(mymap <pass a proper lambda> s))
(double-list-elements-one '(1 2 3 4 5))
=> '(2 4 6 8 10)
Okay, I am new with scheme/racket/lisp. I am practicing creating my own functions, syntax, and recursion, so I want to make my own foldl and foldr functions that do exactly what the predefined versions do. I can't do it because I just don't understand how these functions work. I have seen similar questions on here but I still don't get it. Some examples broken down would help! Here is my (incorrect) process:
(foldl - 0 '(1 2 3 4)) I do 0 -(4-3-2-1) and get 2 which is the right answer
(foldl - 0 '(4 3 2 1)) I do 0-(1-2-3-4) and get 8 but it should be -2.
(foldr - 0 '(1 2 3 4)) I do 0-(1-2-3-4) and get 8 again, but it should be -2.
(foldr - 0 '(4 3 2 1)) I do 0-(4-3-2-1) and get 2 which is the right answer.
What am I doing wrong?
Let's look at: (foldr - 0 '(1 2 3 4)).
Here the literal '(1 2 3 4) constructs a list whose elements are the numbers 1, 2, 3, and, 4. Let's make the construction of the list explicit:
(cons 1 (cons 2 (cons 3 (cons 4 empty))))
One can think of foldr as a function that replaces cons with a function f and empty with a value v.
Therefore
(foldr f 0 (cons 1 (cons 2 (cons 3 (cons 4 empty)))))
becomes
(f 1 (f 2 (f 3 (f 4 v)))))
If the function f is - and the value v is 0, you will get:
(- 1 (- 2 (- 3 (- 4 0)))))
And we can calculate the result:
(- 1 (- 2 (- 3 (- 4 0))))
= (- 1 (- 2 (- 3 4)))
= (- 1 (- 2 -1))
= (- 1 3)
= -2
Note that (foldr cons empty a-list) produces a copy of a-list.
The function foldl on the other hand uses the values from the other side:
> (foldl cons empty '(1 2 3 4))
'(4 3 2 1)
In other words:
(foldl f v '(1 2 3 4))
becomes
(f 4 (f 3 (f 2 (f 1 v)))).
If f is the function - and the value is 0, then we get:
(- 4 (- 3 (- 2 (- 1 0))))
= (- 4 (- 3 (- 2 1)))
= (- 4 (- 3 1))
= (- 4 2)
= 2
Note that (foldl cons empty a-list) produces the reverse of a-list.
You can illustrate what is going on in fold, if you create a procedure, which does the same like cons but reverses the arguments. I have called it snoc in the following example.
(define fldl
(lambda (proc a lst)
(if (pair? lst)
(fldl proc
(proc (car lst)
a)
(cdr lst))
a)))
(define fldr
(lambda (proc a lst)
(if (pair? lst)
(proc (car lst)
(fldr proc
a
(cdr lst)))
a)))
(define lst (list 1 2 3 4))
(fldl + 0 lst) ;; => 10
(fldl * 1 lst) ;; => 24
(fldl cons '() lst) ;; => (4 3 2 1)
(fldr + 0 lst) ;; => 10
(fldr * 1 lst) ;; => 24
(fldr cons '() lst) ;; => (1 2 3 4)
(define snoc (lambda (a b) (cons b a)))
(fldl snoc '() lst) ;; => ((((() . 1) . 2) . 3) . 4)
(fldr snoc '() lst) ;; => ((((() . 4) . 3) . 2) . 1)
Im trying to do the following in the list below: Let say list one consists of (1234) and list 2 is (5678) I am trying to print it in the following way (15263748) This is what I have for now but I am not sure where to go after this. Of course right now the code below prints it like 12 34 it should be 1 3 2 4
(define (arrange-list lst1 lst2)
(append lst1 lst2))
(arrange-list '(12) '(34))
This is a common procedure, usually known as interleave. Assuming that the input lists have the same length, we can write the following implementation from scratch, using explicit recursion:
(define (interleave lst1 lst2)
(if (null? lst1)
'()
(cons (car lst1)
(interleave lst2 (cdr lst1)))))
The trick is taking one element from one list, and then from the other until both lists are exhausted. A more idiomatic solution in Racket would be to use built-in procedures, like this:
(define (interleave lst1 lst2)
(flatten (map cons lst1 lst2)))
Either way it works as expected:
(interleave '(1 2 3 4) '(5 6 7 8))
=> '(1 5 2 6 3 7 4 8)
If the lists aren't of equal length, this is my solution which works albeit is not as elegant as the one mentioned in the other answer.
Basically, we maintain a variable x while recursively calling the procedure that indicates which list needs processing currently. The first list is indicated by 1 and the second, 2.
(define (print-alt A B x)(cond
((and (null? A) (null? B)) '())
((= 1 x) (cond
((null? A) (print-alt A B 2))
(else (append (list (car A)) (print-alt (cdr A) B 2)))))
(else (cond
((null? B) (print-alt A B 1))
(else (append (list (car B)) (print-alt A (cdr B) 1)))))))
Here is the output:
(print-alt (list 1 2 3 4 5 6) (list 5 6 7 8 9 10 11 12 123) 1)
(1 5 2 6 3 7 4 8 5 9 6 10 11 12 123)