How do foldl and foldr work, broken down in an example? - scheme

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)

Related

Scheme recursive

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))))))

Circular permutation in scheme

Hello I try to make circular permutations in Scheme (Dr. Racket) using recursion.
For example, if we have (1 2 3) a circular permutation gives ((1 2 3) (2 3 1) (3 1 2)).
I wrote a piece of code but I have a problem to make the shift.
My code:
(define cpermit
(lambda (lst)
(cpermitAux lst (length lst))))
(define cpermitAux
(lambda (lst n)
(if (zero? n) '()
(append (cpermitAux lst (- n 1)) (cons lst '())))))
Where (cpermit '(1 2 3)) gives '((1 2 3) (1 2 3) (1 2 3))
You can use function that shifts your list
(defun lshift (l) (append (cdr l) (list (car l))))
This will shift your list left.
Use this function before appendings
(define cpermit
(lambda (lst)
(cpermitAux lst (length lst))))
(define cpermitAux
(lambda (lst n)
(if (zero? n) '()
(append (cpermitAux (lshift lst) (- n 1)) (lshift (cons lst '()))))))
This answer is a series of translations of #rnso's code, modified to use a recursive helper function instead of repeated set!.
#lang racket
(define (cpermit sl)
;; n starts at (length sl) and goes towards zero
;; sl starts at sl
;; outl starts at '()
(define (loop n sl outl)
(cond [(zero? n) outl]
[else
(loop (sub1 n) ; the new n
(append (rest sl) (list (first sl))) ; the new sl
(cons sl outl))])) ; the new outl
(loop (length sl) sl '()))
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
For a shorthand for this kind of recursive helper, you can use a named let. This brings the initial values up to the top to make it easier to understand.
#lang racket
(define (cpermit sl)
(let loop ([n (length sl)] ; goes towards zero
[sl sl]
[outl '()])
(cond [(zero? n) outl]
[else
(loop (sub1 n) ; the new n
(append (rest sl) (list (first sl))) ; the new sl
(cons sl outl))]))) ; the new outl
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
To #rnso, you can think of the n, sl, and outl as fulfilling the same purpose as "mutable variables," but this is really the same code as I wrote before when I defined loop as a recursive helper function.
The patterns above are very common for accumulators in Scheme/Racket code. The (cond [(zero? n) ....] [else (loop (sub1 n) ....)]) is a little annoying to write out every time you want a loop like this. So instead you can use for/fold with two accumulators.
#lang racket
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (append (rest sl) (list (first sl))) ; the new sl
(cons sl outl)))) ; the new outl
outl)
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
You might have noticed that the outer list has the (list 1 2 3 4) last, the (list 2 3 4 1) second-to-last, etc. This is because we built the list back-to-front by pre-pending to it with cons. To fix this, we can just reverse it at the end.
#lang racket
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (append (rest sl) (list (first sl))) ; the new sl
(cons sl outl)))) ; the new outl
(reverse outl))
> (cpermit (list 1 2 3 4))
(list (list 1 2 3 4) (list 2 3 4 1) (list 3 4 1 2) (list 4 1 2 3))
And finally, the (append (rest sl) (list (first sl))) deserves to be its own helper function, because it has a clear purpose: to rotate the list once around.
#lang racket
;; rotate-once : (Listof A) -> (Listof A)
;; rotates a list once around, sending the first element to the back
(define (rotate-once lst)
(append (rest lst) (list (first lst))))
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (rotate-once sl) ; the new sl
(cons sl outl)))) ; the new outl
(reverse outl))
> (cpermit (list 1 2 3 4))
(list (list 1 2 3 4) (list 2 3 4 1) (list 3 4 1 2) (list 4 1 2 3))
Following code also works (without any helper function):
(define (cpermit sl)
(define outl '())
(for((i (length sl)))
(set! sl (append (rest sl) (list (first sl))) )
(set! outl (cons sl outl)))
outl)
(cpermit '(1 2 3 4))
Output is:
'((1 2 3 4) (4 1 2 3) (3 4 1 2) (2 3 4 1))
Following solution is functional and short. I find that in many cases, helper functions can be replaced by default arguments:
(define (cpermit_1 sl (outl '()) (len (length sl)))
(cond ((< len 1) outl)
(else (define sl2 (append (rest sl) (list (first sl))))
(cpermit_1 sl2 (cons sl2 outl) (sub1 len)))))
The output is:
(cpermit_1 '(1 2 3 4))
'((1 2 3 4) (4 1 2 3) (3 4 1 2) (2 3 4 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)

How to count and remove element at the same time in the list in Scheme

I have two procedures, one for counting an element in the list and the other one for removing the same element from the same list. What should I do for counting and removing at the same time? I am trying it for long time but nothing is working. I work with this list: (list 1 2 3 2 1 2 3), finally it should be like: ((1 . 2) (2 . 3) (3 . 2)). The first number of pair is an element and second number of pair is sum of first pair's number from all list.
My try:
1) it works only with counting and result is: ((1 . 2) (2 . 3) (3 . 2) (2 . 2) (1 . 1) (2 . 1) (3 . 1))
2) it works only with removing and result is: ((1 . 2) 2 3 2 2 3)
Where is the problem?
This is for counting:
(define count-occurrences
(lambda (x ls)
(cond
[(memq x ls) =>
(lambda (ls)
(+ (count-occurrences x (cdr ls)) 1))]
[else 0])))
(count-occurrences '2 (list 1 2 3 2 1 2 3)) -> 3
This is for removing:
(define (remove-el p s)
(cond ((null? s) '())
((equal? p (car s)) (remove-el p (cdr s)))
(else (cons (car s) (remove-el p (cdr s))))))
(remove-el '2 (list 1 2 3 2 1 2 3)) -> (1 3 1 3)
Just return the count and the removed list at once. I call this routine
count-remove. (Pardon to all schemers for not idiomatic or efficient style)
(define (count-remove ls x)
(letrec ([loop (lambda (count l removed)
(cond
[(eq? l '()) (list count removed)]
[(eq? (car l) x) (loop (+ 1 count) (cdr l) removed)]
[else (loop count (cdr l) (cons (car l) removed))]))])
(loop 0 ls '())))
(define (count-map ls)
(cond
[(eq? ls '()) '()]
[else
(letrec ([elem (car ls)]
[cr (count-remove ls elem)])
(cons (cons elem (car cr)) (count-map (cadr cr))))]))
Here is some usage:
(count-map '(1 1 2 3 2))
((1 . 2) (2 . 2) (3 . 1))

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