Explication of Scheme code for permutations - scheme

Here is a Scheme code to produce the permutations of a list of elements:
(define (remove x lst) (cond
((null? lst) '())
((= x (car lst)) (remove x (cdr lst)))
(else (cons (car lst) (remove x (cdr lst))))))
(define (permute lst) (cond
((= (length lst) 1) (list lst))
(else (apply append
(map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst)))) lst)))))
I do understand each part of the code if we take the code apart, but what I can’t understand is how this all leads to generating the permutations?
Let’s say we take the list ‘(a b), how does it generate ‘(a b) and ‘(b a)?
We start by removing a from the list and b stays, but where is written that you now have to cons a to b? b is a single element, but in my interpretation of the code, b will also be removed and there is nothing left…

I would read the main part like this (in the order indicated by numbers)
(map (lambda (i) ;(1) for each i in...
(map (lambda (j) ;(3) for each j in...
(cons i j)) ;(6) append i to front (of this shorter permutation)
(permute ;(4) ...the list of all permutations...
(remove i lst)))) ;(5) ...of the input list with i removed
lst) ;(2) ... the input list

(TL;DR: the verbal explanation is at the very end of this answer.)
Let's try following the definitions with let*-rewrites. The definitions are
(define (remove x lst) (cond
((null? lst) '())
((= x (car lst)) (remove x (cdr lst)))
(else (cons (car lst) (remove x (cdr lst))))))
(define (permute lst) (cond
((= (length lst) 1) (list lst))
(else (apply append
(map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst)))) lst)))))
We try
(permute '(a b))
≡
(let* ((lst '(a b)))
(apply append
(map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst))))
lst)))
≡
(let* ((lst '(a b))
(r (map (lambda (i)
(map (lambda (j) (cons i j))
(permute (remove i lst))))
lst)))
(apply append r))
≡
(let* ((lst '(a b))
(i1 'a)
(r1 (map (lambda (j) (cons i1 j))
(permute (remove i1 lst))))
(i2 'b)
(r2 (map (lambda (j) (cons i2 j))
(permute (remove i2 lst))))
(r (list r1 r2)))
(apply append r))
≡
(let* ((lst '(a b))
(i1 'a)
(t1 (permute (remove i1 lst)))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 (permute (remove i2 lst)))
(r2 (map (lambda (j) (cons i2 j)) t2))
(r (list r1 r2)))
(apply append r))
≡
(let* ((i1 'a)
(t1 (permute '(b)))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 (permute '(a)))
(r2 (map (lambda (j) (cons i2 j)) t2))
(r (list r1 r2)))
(apply append r))
≡
(let* ((i1 'a)
(t1 '( (b) ))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 '( (a) ))
(r2 (map (lambda (j) (cons i2 j)) t2))
(r (list r1 r2)))
(apply append r))
and so we get
(let* ((r1 (map (lambda (j) (cons 'a j)) '( (b) )))
(r2 (map (lambda (j) (cons 'b j)) '( (a) )))
(r (list r1 r2)))
(apply append r))
≡
(let* ((r1 (list (cons 'a '(b))))
(r2 (list (cons 'b '(a))))
(r (list r1 r2)))
(apply append r))
≡
(let* ((r1 (list '(a b)))
(r2 (list '(b a)))
(r (list r1 r2)))
(apply append r))
≡
(let* ((r1 '((a b)))
(r2 '((b a)))
(r (list r1 r2)))
(apply append r))
≡
(apply append (list '((a b)) '((b a))))
≡
( append '((a b)) '((b a)) )
≡
'( (a b) (b a) )
Follow the same technique if you need to convince yourself in the validity of the intermediate results.
In hindsight, we could simplify it a bit more aggressively, like
(let* ((lst '(a b))
(i1 'a)
(r1 (map (lambda (j) (cons i1 j))
(permute (remove i1 lst))))
(i2 'b)
(r2 (map (lambda (j) (cons i2 j))
(permute (remove i2 lst))))
(r (list r1 r2)))
(apply append r))
≡
(let* ((lst '(a b))
(i1 'a)
(t1 (permute (remove i1 lst)))
(r1 (map (lambda (j) (cons i1 j)) t1))
(i2 'b)
(t2 (permute (remove i2 lst)))
(r2 (map (lambda (j) (cons i2 j)) t2)))
(apply append (list r1 r2)))
≡
(let* ((t1 (permute '(b)))
(r1 (map (lambda (j) (cons 'a j)) t1))
(t2 (permute '(a)))
(r2 (map (lambda (j) (cons 'b j)) t2)))
(append r1 r2))
≡
(let* ((r1 (map (lambda (j) (cons 'a j)) '( (b) )))
(r2 (map (lambda (j) (cons 'b j)) '( (a) )))
)
(append r1 ; one row for each elt '( a
r2 ; of the input list, b
)) ; spliced in place by append )
etc., in the end revealing the structure of the computation in the more visually apparent manner:
for each element of the input list,
find all the permutations of the remainder,
prepend that element to each of them,
and join together the results from thus processing each element in the input list, by appending all those results together.
(thus justifying my other, pseudocode-based answer here).

(apply append (map f xs)) == (flatmap f xs).
Re-writing your code in an equational pattern-matching pseudocode,
remove x [x, ...ys] = remove x ys ; skip this x, and go on removing
; ( consider skipping just this one occurrence instead:
; = ys )
remove x [y, ...ys] = [y, ...remove x ys] ; (or else x /= y, so keep this y)
remove x [] = [] ; until the list is exhausted
permute [x] = [[x]]
permute xs =
xs ; ( with (xs |> f) == (f xs) )
|> flatmap (x => ; for each x in xs,
permute (remove x xs) ; for each permutation p of xs w/o x,
|> map (p => [x, ...p]) ) ; prepend x to p and
; splice the results in place of x
Is this clearer?
No? So, let's see how permute [a,b] is calculated.
First, what is permute [a]?
permute [a] = ...
( permute [x] = [[x]] )
... = [[a]]
(it doesn't matter how we call the first element of a single-element list, it's still its first and only element). Similarly,
permute [b] = ...
( permute [x] = [[x]] )
... = [[b]]
OK, but how does it help us see what's the result of permute [a,b]? Let's work with it step by step:
permute [ a, b ] =
;; for each x in (xs==[a,b])
;; a b ; <<- the value of x
;; remove x from xs
;; [b] [a] ; <<- xs with x removed
;; prepend x to each permutation of the above
;; [[ b]] [[ a]] ; <<- permutations
;; [[a,b]] [[b,a]] ; <<- prefixed with x
;; splice them in by `apply append`
[ [a,b] , [b,a] ]
So then, permute [b,c] == [[b,c],[c,b]], etc. And, armed with this knowledge,
permute [ a, b, c ] =
;; for each x in (xs==[a,b,c])
;; remove x from xs
;; [b,c] [a,c] [a,b]
;; prepend x to each permutation of the above
;; [[ b,c],[ c,b]] [[ a,c],[ c,a]] [[ a,b],[ b,a]]
;; [[a,b,c],[a,c,b]] [[b,a,c],[b,c,a]] [[c,a,b],[c,b,a]]
;; splice them in by `apply append`
[ [a,b,c],[a,c,b], [b,a,c],[b,c,a], [c,a,b],[c,b,a] ]
Is that clearer?

Related

Scheme insertion sort without using primitive functions (car, cdr, cons)

I'm trying to write function for insertion sort with and without primitive functions.
My code with primitive functions is below.
(define (insert n d)
(cond ((null? n) d)
((null? d) n)
(else (< (car n) (car d)) (cons (car n) (insert (cdr n) d)) (cons (car d) (insert (cdr d) n)))))
(define (sort n)
(cond ((null? n) '())
(else (insert (list (car n)) (sort (cdr n))))))
How should I revise insert and sort to not use car, cdr, and cons?
Edit: I tried to write the insert function. This is what I have so far.
(define (insert n d)
(let ((rest-digit (truncate (/ n 10))))
(if (null? n) 0
(+ rest-digit (insert (- n 1) d)))))
(insert '(3 2 1) '5)
Edit #2: I think I can use the built-in function expt.
Ultimately you will be using primitive functions. To illustrate let me show you a trick that actually uses cons, car, and cdr under the hood:
(define (my-car lst)
(apply (lambda (a . d) a) lst))
(define (my-cdr lst)
(apply (lambda (a . d) d) lst))
(define (my-cons a d)
(apply (lambda l l) a d))
(define test (my-cons 1 '(2 3)))
test ; ==> (1 2 3)
(my-car test) ; ==> 1
(my-cdr test) ; ==> (2 3)
This abuses the fact that apply takes a list as the final arguments and that rest arguments are cons-ed onto a list in order. cons doesn't work for all pairs:
(my-cons 1 2) ; ERROR: expected list?, got 1
You can make cons, car, and cdr such that they adher to the same rules as primitive cons, but that they are not made of pairs at all. Barmar suggested closures:
(define (ccons a d)
(lambda (f) (f a d))
(define (ccar cc)
(cc (lambda (a d) a)))
(define (ccdr cc)
(cc (lambda (a d) d)))
(define test2 (ccons 1 2))
test2 ; ==> #<function...>
(ccar test2) ; ==> 1
(ccdr test2) ; ==> 2
This works since a and d gets closed over in the returned function and that function passes those values and thus the function acts as an object with two attributes. The challenge with this is that you cannot just pass a list since only "lists" made with ccons will work with ccar and ccdr.
A less classical way is to use vectors:
(define vtag (make-vector 0))
(define (vcons a d)
(let ((v (make-vector 3)))
(vector-set! v 0 vtag)
(vector-set! v 1 a)
(vector-set! v 2 d)
v))
(define (vcar vl)
(vector-ref vl 1))
(define (vcdr vl)
(vector-ref vl 2))
(define (vpair? vl)
(eq? vtag (vector-ref vl 0)))
Or you can use records:
(define-record-type :rpair
(rcons a d)
rpair?
(a rcar)
(d rcdr))
(define test (rcons 1 2))
(rpair? test) ; ==> #t
(rcar test) ; ==> 1
(rcdr test) ; ==> 2
Now I think records just syntax sugar and abstractions and that under the hood you are doing exactly the same as the vector version with less code, but that isn't a bad thing.
EDIT
So from the comments if the only restriction is to avoid car, cdr, and cons, but no restrictions on their sisters we might as well implement with them:
(define (sort lst)
(define (insert e lst)
(if (null? lst)
(list e)
(let ((a (first lst)))
(if (>= a e)
(list* e lst)
(list* a (insert e (rest lst)))))))
(foldl insert
'()
lst))
(sort '(1 5 3 8 5 0 2))
; ==> (0 1 2 3 5 5 8)
And of course my first suggestion works in its place:
(define (sort lst)
(define (my-car lst)
(apply (lambda (a . d) a) lst))
(define (my-cdr lst)
(apply (lambda (a . d) d) lst))
(define (my-cons a d)
(apply (lambda l l) a d))
(define (insert e lst)
(if (null? lst)
(my-cons e '())
(let ((a (my-car lst)))
(if (>= a e)
(my-cons e lst)
(my-cons a (insert e (my-cdr lst)))))))
(foldl insert
'()
lst))
And of course, using substitution rules you can make it utterly ridiculous:
(define (sort lst)
;; insert element e into lst in order
(define (insert e lst)
(if (null? lst)
((lambda l l) e)
(let ((a (apply (lambda (a . d) a) lst)))
(if (>= a e)
(apply (lambda l l) e lst)
(apply (lambda l l)
a
(insert e (apply (lambda (a . d) d) lst)))))))
;; main loop of sort
;; insert every element into acc
(let loop ((lst lst) (acc '()))
(if (null? lst)
acc
(loop (apply (lambda (a . d) d) lst)
(insert (apply (lambda (a . d) a) lst)
acc)))))

Scheme set made from parts of set

Hi i'm trying to define a function which should make a set from the parts of that set.
Should be defined like: P(A) = P(A-{x}) U { {x} U B} for all B that belongs to P(A-{X}) where X belongs to A.
A test would be:
(parts '(a b c))
=> ((a b c) (a b) (a c) (a) (b c) (b) (c)())
I've been trying with this one:
(define (mapc f x l)
(if (null? l)
l
(cons (f x (car l)) (mapc f x (cdr l)))))
Maybe something like this? (untested)
(define (power-set A)
(cond
[(null? A) '()] ; the power set of an empty set it empty
[else (append (map (lambda (S) (cons x S)) ; sets with x
(power-set (cdr A)))
(power-set (cdr A)) ; sets without x
]))
This is essentially 'combinations' function (https://docs.racket-lang.org/reference/pairs.html?q=combinations#%28def._%28%28lib._racket%2Flist..rkt%29._combinations%29%29).
Following short code in Racket (a Scheme derivative) gets all combinations or parts:
(define (myCombinations L)
(define ol (list L)) ; Define outlist and add full list as one combination;
(let loop ((L L)) ; Recursive loop where elements are removed one by one..
(for ((i L)) ; ..to create progressively smaller combinations;
(define K (remove i L))
(set! ol (cons K ol)) ; Add new combination to outlist;
(loop K)))
(remove-duplicates ol))
Testing:
(myCombinations '(a b c))
Output:
'(() (a) (b) (a b) (c) (a c) (b c) (a b c))

filter function using tail recursion

Currently I have
(define filter
(λ (f xs)
(letrec [(filter-tail
(λ (f xs x)
(if (empty? xs)
x
(filter-tail f (rest xs)
(if (f (first xs))
(cons (first xs) x)
'()
)))))]
(filter-tail f xs '() ))))
It should be have as a filter function
However it outputs as
(filter positive? '(-1 2 3))
>> (3 2)
but correct return should be (2 3)
I was wondering if the code is correctly done using tail-recursion, if so then I should use a reverse to change the answer?
I was wondering if the code is correctly done using tail-recursion.
Yes, it is using a proper tail call. You have
(define (filter-tail f xs x) ...)
Which, internally is recursively applied to
(filter-tail f
(some-change-to xs)
(some-other-change-to x))
And, externally it's applied to
(filter-tail f xs '())
Both of these applications are in tail position
I should use a reverse to change the answer?
Yep, there's no way around it unless you're mutating the tail of the list (instead of prepending a head) as you build it. One of the comments you received alluded to this using set-cdr! (see also: Getting rid of set-car! and set-cdr!). There may be other techniques, but I'm unaware of them. I'd love to hear them.
This is tail recursive, requires the output to be reversed. This one uses a named let.
(define (filter f xs)
(let loop ([ys '()]
[xs xs])
(cond [(empty? xs) (reverse ys)]
[(f (car xs)) (loop (cons (car xs) ys) (cdr xs))]
[else (loop ys (cdr xs))])))
(filter positive? '(-1 2 3)) ;=> '(2 3)
Here's another one using a left fold. The output still has to be reversed.
(define (filter f xs)
(reverse (foldl (λ (x ys) (if (f x) (cons x ys) ys))
'()
xs)))
(filter positive? '(-1 2 3)) ;=> '(2 3)
With the "difference-lists" technique and curried functions, we can have
(define (fold c z xs)
(cond ((null? xs) z)
(else (fold c (c (car xs) z) (cdr xs)))))
(define (comp f g) (lambda (x) ; ((comp f g) x)
(f (g x))))
(define (cons1 x) (lambda (y) ; ((cons1 x) y)
(cons x y)))
(define (filter p xs)
((fold (lambda (x k)
(if (p x)
(comp k (cons1 x)) ; nesting's on the left
k))
(lambda (x) x) ; the initial continuation, IC
xs)
'()))
(display (filter (lambda (x) (not (zero? (remainder x 2)))) (list 1 2 3 4 5)))
This builds
comp
/ \
comp cons1 5
/ \
comp cons1 3
/ \
IC cons1 1
and applies '() to it, constructing the result list in the efficient right-to-left order, so there's no need to reverse it.
First, fold builds the difference-list representation of the result list in a tail recursive manner by composing the consing functions one-by-one; then the resulting function is applied to '() and is reduced, again, in tail-recursive manner, by virtues of the comp function-composition definition, because the composed functions are nested on the left, as fold is a left fold, processing the list left-to-right:
( (((IC+k1)+k3)+k5) '() ) ; writing `+` for `comp`
=> ( ((IC+k1)+k3) (k5 '()) ) ; and `kI` for the result of `(cons1 I)`
<= ( ((IC+k1)+k3) l5 ) ; l5 = (list 5)
=> ( (IC+k1) (k3 l5) )
<= ( (IC+k1) l3 ) ; l3 = (cons 3 l5)
=> ( IC (k1 l3) )
<= ( IC l1 ) ; l1 = (cons 1 l3)
<= l1
The size of the function built by fold is O(n), just like the interim list would have, with the reversal.

Scheme Loop Through a List

How would I loop this list in scheme?
(define test-document '(
((h e l l o))
((t h i s)(i s)(t e s t))
))
What I tried it only showed the first column.
car and cdr family of functions are your friends to navigate lists. Here are some examples.
(define test-document '(
((h e l l o))
((t h i s)(i s)(t e s t))
))
(car test-document) ;; `((h e l l o))
(caar test-document) ;; `(h e l l o)
(cadr test-document) ;; `((t h i s) (i s) (t e s t))
(car (cadr test-document) ;; `(t h i s)
(cadr (cadr test-document) ;; `(i s)
(caddr (cadr test-document) ;; `(test )
Define a function that will walk the list and call a function for each item that is not a list.
(define (walk-list lst fun)
(if (not (list? lst))
(fun lst)
(if (not (null? lst))
(begin
(walk-list (car lst) fun)
(walk-list (cdr lst) fun)))))
Call it to print each item.
(walk-list test-document print)
What you have is a list of lists of lists:
(define test-document '(((h e l l o)) ((t h i s) (i s) (t e s t))))
To loop over its elements you must create a loop of a loop of a loop. To do so we can use map and curry as follows:
(map (curry map (curry map
(compose string->symbol string-upcase symbol->string)))
test-document)
This produces the following output:
(((H E L L O)) ((T H I S) (I S) (T E S T)))
If your Scheme interpreter doesn't have a built-in curry function then you can define one as follows:
(define (curry func . args)
(lambda x (apply func (append args x))))
Hope this helped.
Were you thinking of something like this?
(define (walk-list lst)
(define (sub-walk lst)
(if (null? lst)
'()
(let ((x (car lst)))
(if (list? x)
(cons (sub-walk x) (sub-walk (cdr lst)))
(apply string-append (map symbol->string lst))))))
(flatten (sub-walk lst)))
then
(walk-list test-document)
=> '("hello" "this" "is" "test")
which you can process using the usual suspects (map, filter, ...).
If your Scheme has no flatten procedure, you can use this one:
(define (flatten lst)
(reverse
(let loop ((lst lst) (res null))
(if (null? lst)
res
(let ((c (car lst)))
(loop (cdr lst) (if (pair? c) (loop c res) (cons c res))))))))

Sorting in scheme following a pattern

A little help, guys.
How do you sort a list according to a certain pattern
An example would be sorting a list of R,W,B where R comes first then W then B.
Something like (sortf '(W R W B R W B B)) to (R R W W W B B B)
Any answer is greatly appreciated.
This is a functional version of the Dutch national flag problem. Here are my two cents - using the sort procedure with O(n log n) complexity:
(define sortf
(let ((map '#hash((R . 0) (W . 1) (B . 2))))
(lambda (lst)
(sort lst
(lambda (x y) (<= (hash-ref map x) (hash-ref map y)))))))
Using filter with O(4n) complexity:
(define (sortf lst)
(append (filter (lambda (x) (eq? x 'R)) lst)
(filter (lambda (x) (eq? x 'W)) lst)
(filter (lambda (x) (eq? x 'B)) lst)))
Using partition with O(3n) complexity::
(define (sortf lst)
(let-values (((reds others)
(partition (lambda (x) (eq? x 'R)) lst)))
(let-values (((whites blues)
(partition (lambda (x) (eq? x 'W)) others)))
(append reds whites blues))))
The above solutions are written in a functional programming style, creating a new list with the answer. An optimal O(n), single-pass imperative solution can be constructed if we represent the input as a vector, which allows referencing elements by index. In fact, this is how the original formulation of the problem was intended to be solved:
(define (swap! vec i j)
(let ((tmp (vector-ref vec i)))
(vector-set! vec i (vector-ref vec j))
(vector-set! vec j tmp)))
(define (sortf vec)
(let loop ([i 0]
[p 0]
[k (sub1 (vector-length vec))])
(cond [(> i k) vec]
[(eq? (vector-ref vec i) 'R)
(swap! vec i p)
(loop (add1 i) (add1 p) k)]
[(eq? (vector-ref vec i) 'B)
(swap! vec i k)
(loop i p (sub1 k))]
[else (loop (add1 i) p k)])))
Be aware that the previous solution mutates the input vector in-place. It's quite elegant, and works as expected:
(sortf (vector 'W 'R 'W 'B 'R 'W 'B 'B 'R))
=> '#(R R R W W W B B B)
This is a solution without using sort or higher order functions. (I.e. no fun at all)
This doesn't really sort but it solves your problem without using sort. named let and case are the most exotic forms in this solution.
I wouldn't have done it like this unless it's required not to use sort. I think lepple's answer is both elegant and easy to understand.
This solution is O(n) so it's probably faster than the others with very large number of balls.
#!r6rs
(import (rnrs base))
(define (sort-flag lst)
;; count iterates over lst and counts Rs, Ws, and Bs
(let count ((lst lst) (rs 0) (ws 0) (bs 0))
(if (null? lst)
;; When counting is done build makes a list of
;; Rs, Ws, and Bs using the frequency of the elements
;; The building is done in reverse making the loop a tail call
(let build ((symbols '(B W R))
(cnts (list bs ws rs))
(tail '()))
(if (null? symbols)
tail ;; result is done
(let ((element (car symbols)))
(let build-element ((cnt (car cnts))
(tail tail))
(if (= cnt 0)
(build (cdr symbols)
(cdr cnts)
tail)
(build-element (- cnt 1)
(cons element tail)))))))
(case (car lst)
((R) (count (cdr lst) (+ 1 rs) ws bs))
((W) (count (cdr lst) rs (+ 1 ws) bs))
((B) (count (cdr lst) rs ws (+ 1 bs)))))))
Make a lookup eg
(define sort-lookup '((R . 1)(W . 2)(B . 3)))
(define (sort-proc a b)
(< (cdr (assq a sort-lookup))
(cdr (assq b sort-lookup))))
(list-sort sort-proc '(W R W B R W B B))
Runnable R6RS (IronScheme) solution here: http://eval.ironscheme.net/?id=110
You just use the built-in sort or the sort you already have and use a custom predicate.
(define (follow-order lst)
(lambda (x y)
(let loop ((inner lst))
(cond ((null? inner) #f)
((equal? x (car inner)) #t)
((equal? y (car inner)) #f)
(else (loop (cdr inner)))))))
(sort '(W R W B R W B) (follow-order '(R W B)))
;Value 50: (r r w w w b b)

Resources