Scheme problem (using a function as a parameter) - scheme

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)

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)

How To Mutate Variables Scheme

I'm trying to sum a list using mutable objects for an assignment.letis used here to allow me to mutate x the total sum and counter. I'm not very well versed with scheme hence the use if statements for each number in the list lst:
(define lst (list 1 2 3 4 5))
(let mut ((counter 0))
(let ((x (car lst)))
(if (= counter 4)
x)
(if (= 0 counter)
(+ x (cadr lst)))
(if (= 1 counter)
(display (caddr lst)) ;test
(+ x (caddr lst)))
(if (= 2 counter)
(+ x (caddr lst)))
(set-car! lst (cdr lst))
(mut (+ counter 1))
)
)
however when I run the code I get an error
+: contract violation
expected: number?
given: (mcons 2 (mcons 3 (mcons 4 (mcons 5 '()))))
argument position: 1st
other arguments...:
However when I check (caddr lst) it returns a 3 as expected. My issue is why, when run, does caddr produce (mcons 2 (mcons 3 (mcons 4 (mcons 5 '())))) when applied to an + but when not applied it returns 3
I am using R5RS
edit: I have omitted some of the if statements for conciseness
Okay so I figured it out using a whole different implementation #molbdnilo was correct that my understanding was flawed.
here is my implementation if anyone else is struggling with this problem
(define (goMut)
(define mVar 0)
(define acc 0)
(define (accDo num)
(set! acc (+ num acc)))
(for-each (lambda (x) (set! mVar x) (accDo x))
(list 1 2 3 4 5))
acc
)
Using set! we can apply the value in the list to an external variable and mutate it as we iterate throughout the loop using the function accDo. Function template taken from SICP pg 107

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 do foldl and foldr work, broken down in an example?

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)

How to split a list into two parts in Scheme

Example: (split '(1 2 3 4) '3)
the Answer should be: ((1 2 3) 4)
The function required 1 list and 1 number, the output should be nested list
the nested list consist of all elements of "mylist" which are equal or less than the "num", and the greater number should be on the right of the list.
I tried but out put is only one list:
(define (split mylist num)
(cond
((null? mylist)'())
((list? (car mylist))(split(car mylist) num))
((> (car mylist) num)(split(cdr mylist) num))
(else(cons (car mylist) (split(cdr mylist) num)))))
A simple solution:
(define (split-list xs y)
(define (less x) (<= x y))
(define (greater x) (> x y))
(list (filter less xs)
(filter greater xs)))
An alternative:
(define (split-list xs y)
(define (less x) (<= x y))
(define-values (as bs) (partition less xs))
(list as bs))
(split-list '(1 2 3 4) 3)
Here's one possible solution, using built-in procedures in Racket:
(define (split mylist num)
(cons
(takef mylist (lambda (n) (<= n num)))
(dropf mylist (lambda (n) (<= n num)))))
For example:
(split '(1 2 3 4) 3)
=> '((1 2 3) 4)
(split '(1 2 3 4 5) 3)
=> '((1 2 3) 4 5)
This is roll your own version using named let. It makes one pass through the data and the result is in reverse order since it's the most effective.
(define (binary-bucket-sort lst threshold)
(let loop ((lst lst) (less-equal '()) (greater '()))
(cond ((null? lst)
(cons less-equal greater))
((<= (car lst) threshold)
(loop (cdr lst) (cons (car lst) less-equal) greater))
(else
(loop (cdr lst) less-equal (cons (car lst) greater))))))
(binary-bucket-sort '(1 5 9 2 6 10 3 7 9 8 4 0) 5)
; ==> ((0 4 3 2 5 1) . (8 9 7 10 6 9))
If you're comfortable with some of the more functional constructs in Racket, such as curry and the like, you can use this rather compact approach:
(define (split-list xs y)
(call-with-values (thunk (partition (curry >= y) xs)) cons))
> (split-list '(1 2 3 4 5 6 7) 3)
'((1 2 3) 4 5 6 7)

Resources