Printing Numbers in Scheme - scheme

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)

Related

How to invert the predicate here?

I have the following filter procedure:
; (2) filter
(define (filter test sequence)
; return a list of the elements that pass the predicate test
(let ((elem (if (null? sequence) nil (car sequence)))
(rest (if (null? sequence) nil (cdr sequence))))
(cond ((null? sequence) nil)
((test elem) (cons elem (filter test rest)))
(else (filter test rest)))))
And here would be an example of using it to return the even-numbered elements of a list:
(define even? (lambda (x) (= (modulo x 2) 0)))
(define sequence '(1 2 3 4 5 8 9 11 13 14 15 16 17))
(filter even? sequence)
; (2 4 8 14 16)
Is there a simple way to use the not test to invert the selection? For example, I thought the following might work:
(filter (not even?) sequence)
But it returns an error. I can define odd separately, of course:
(define odd? (lambda (x) (not (even? x))))
But I'm trying not to do this. Is there a way to write the odd procedure without defining it directly, but instead using the not directly like I'm trying to do above?
There is a complement function in Common Lisp that does what I think you are looking for. complement is a higher-order procedure that takes a procedure as its argument, and returns a procedure that takes the same arguments as the input procedure and performs the same actions, but the returned truth value is inverted.
Racket has a similar procedure, negate, and it is easy enough to implement this in Scheme:
(define (complement f)
(lambda xs (not (apply f xs))))
> (filter even? '(1 2 3 4 5))
(2 4)
> (filter (complement even?) '(1 2 3 4 5))
(1 3 5)
> (> 1 2 3 4 5)
#f
> ((complement >) 1 2 3 4 5)
#t
And in Racket:
scratch.rkt> (filter even? '(1 2 3 4 5))
'(2 4)
scratch.rkt> (filter (negate even?) '(1 2 3 4 5))
'(1 3 5)
scratch.rkt> (> 1 2 3 4 5)
#f
scratch.rkt> ((negate >) 1 2 3 4 5)
#t
The general answer to this is to simply compose not and the function you care about. Racket has a compose function which does this, but you can easily write a simple one yourself:
(define (compose-1 . functions)
;; simple-minded compose: each function other than the last must
;; take just one argument; all functions should return just one
;; value.
(define (compose-loop fns)
(cond
((null? fns)
(λ (x) x))
((null? (cdr fns))
(car fns))
(else
(λ (x) ((car fns) ((compose-loop (cdr fns)) x))))))
(compose-loop functions))
Making it efficient and more general takes more work of course.
Then you can define odd? (which is already defined of course):
(define odd? (compose-1 not even)
Or in fact define a more general CL-style complement function:
(define (complement f)
(compose-1 not f))
One option is to write an invert function which will curry things along (so the initial function still accepts one argument) until the final evaluation occurs:
(define invert (lambda (func) (lambda (x) (not (func x)))))
(define sequence '(1 2 3 4 5 6 8 9 11 13 14 15 16 17))
(filter (invert even?) sequence)
; (1 3 5 9 11 13 15 17)

Scheme: Update a list without using imperative features like set

I have only just started to learn scheme and were asked to implement the quick-sort algorithm in scheme, but we are not allow to use any imperative features like set! and we are not allowed to use filter
I have tried to come up with my own algorithm with this in mind, but I can't seem to avoid the use of set! for updating a list:
(define quicksort
(lambda (L)
(cond
[(or (null? L) (null? (cdr L))) L]
[else (let ((pivot (car L)) (small '()) (large '()))
(do ((i (- (length L) 1) (- i 1)))
((= i 0))
(if (< (list-ref L i) pivot)
(set! small (cons (list-ref L i) small))
(set! large (cons (list-ref L i) large))))
(append (quicksort small) (list pivot) (quicksort large)))])))
This code works, but is there any way of updating the lists small and large without the use of set?
If you cannot use set!, you cannot mutate lists. You are being asked to do this functionally, without any mutation. Instead of modifying a list in-place, build up smaller, partially-sorted lists and then combine them while preserving the sort.
To be fair Quicksort is an in place algorithm and many would state replacing the vectors with lists will change it enough to no longer bee quicksort. I'll ignore this at the moment.
Split large stuff in smaller chunks of code. This way you can test each step:
(segment 5 '(5 1 1 3 8 6 4 9 8 5 3 5 3 8 6))
; ==> ((1 1 3 4 3 3) (5 5) (8 6 9 8 8 6))
Of course you make the simple tests first:
(segment 5 '(5)) ; ==> (() (5) ())
(segment 5 '(5 1)) ; ==> ((1) (5) ())
(segment 5 '(5 8)) ; ==> (() (5) (8))
(segment 5 '(5 8 1 5)) ; ==> ((1) (5 5) (8))
The order of the results in the sub list is not important. eg. the result ((3 3 4 3 1 1) (5 5) (6 8 8 9 6 8)) is equally as sufficient and most probably easier to do.
With that made quicksort by first checking if it is a less than 2 element list eg. (or (null? lst) (null? (cdr lst))) and return the argument or create the 3 segments using the first element as pivot and then append the recursion of the lesser and the higher and then appending the 3 lists together and you have them in order.
As inspiration here is a procedure that splits on odd? and not:
(define (split-odd lst)
(let loop ((lst lst) (odd '()) (even '()))
(cond
((null? lst) (list odd even))
((odd? (car lst)) (loop (cdr lst) (cons (car lst) odd) even))
(else (loop (cdr lst) odd (cons (car lst) even))))))
(split-odd '(1 2 3 4 5 6))
; ==> ((5 3 1) (6 4 2))

Scheme Double All List Values and Write Mapping Function

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)

How to make two lists, one with even numbers and one with odd numbers, in scheme?

I have a problem.
For example:
We have one unsorted list:
(1 4 5 3 6 7)
Can you help me make 2 lists?
One odd numbered, increasing list:
(1 3 5 7)
and the other even numbered, decreasing list:
(6 4)
Don't use sort!
(define (split filter lst)
(let loop ((a '()) (b '()) (lst lst))
(if (null? lst)
(values a b)
(let ((cur (car lst)))
(if (filter cur)
(loop (cons cur a) b (cdr lst))
(loop a (cons cur b) (cdr lst)))))))
(split odd? '(1 2 3 4 5 6 7 8 9 10))
; ==> (9 7 5 3 1), (10 8 6 4 2)
Now, to make one that separates odds from evens and in a specific order would be simple.

Scheme problem (using a function as a parameter)

I'm a Scheme newbie and trying to make sense of my homework.
I've a function I made earlier called duplicate, and it looks like this:
( DEFINE ( duplicate lis )
(IF (NULL? lis) '())
((CONS (CAR lis) (CONS (CAR lis) (duplicate (CDR lis))))
))
A typical i/o from this would be i: (duplicate '(1 2 3 4)) o: (1 1 2 2 3 3 4 4), so basicly it duplicates everything in the list.
Moving on:
Now I'm supposed to make a function that's called comp.
It's supposed to be built like this:
(DEFINE (comp f g) (lambda (x) (f (g (x))))
Where I could input '(1 2 3 4) and it would return (1 1 4 4 9 9 16 16)
so f = duplicate and g = lambda.
I know lambda should probably look like this:
(lambda (x) (* x x))
But here's where the problem starts, I've already spent several hours on this, and as you can see not made much progress.
Any help would be appreciated.
Best regards.
Use map:
> (map (lambda (x) (* x x)) (duplicate '(1 2 3 4)))
=> (1 1 4 4 9 9 16 16)
or, modify duplicate to take a procedure as its second argument and apply it to each element of the list:
(define (duplicate lst p)
(if (null? lst) ()
(append (list (p (car lst)) (p (car lst))) (duplicate (cdr lst) p))))
> (duplicate '(1 2 3 4) (lambda (x) (* x x)))
=> (1 1 4 4 9 9 16 16)
One way to do is as follows:
(define (comp f g) (lambda (x) (f (g x))))
(define (square x) (* x x))
(define (dup x) (list x x))
(define (duplicate-square lst)
(foldr append '() (map (comp dup square) lst)))
Now at the repl, do:
> (duplicate-square '(1 2 3 4))
'(1 1 4 4 9 9 16 16)

Resources