So here is one approach to doing this. I assume you are allowed to write helper functions.
The first step is to realise that at some point you are going to need to take a list of elements and 'thread' something through it, producing all the possible new lists with that element inserted somewhere. So given (1 2)
and 3
you want to make ((3 1 2) (1 3 2) (1 2 3))
.
And for reasons which will become clear I'm going to do this in such a way that the function adds its answers to some preexisting ones. And it's going to have, itself, a little helper function.
(define (thread-list e l into)
;; Thread e through l accumulating into into
(thread-list-loop e '() l into))
(define (thread-list-loop e before after into)
;; Do the work of threading e through a list:
;; - before is the chunk of list before e;
;; - after is the chunk after e;
;; - into is what we're collecting into
(if (null? after)
;; We now just need before with e at the end
(cons (append before (list e)) into)
;; add the current thing to results and loop
(thread-list-loop
e
(append before (list (first after)))
(rest after)
(cons (append before (list e) after) into))))
So let's test this:
> (thread-list 1 '(2 3) '())
'((2 3 1) (2 1 3) (1 2 3))
Now we want a function which will take an element, and a bunch of lists, and thread the element through each of the lists, accumulating the result:
(define (thread-lists e lists into)
;; thread e through each element of lists, accumulating into into
(if (null? lists)
into
(thread-lists
e
(rest lists)
(thread-list e (first lists) into))))
And checking this:
> (thread-lists 1 '((2 3) (3 2)) '())
'((3 2 1) (3 1 2) (1 3 2) (2 3 1) (2 1 3) (1 2 3))
And I'm going to stop here, but look at what the above call did: given ((2 3) (3 2))
, which is the permutations of (2 3)
, and 1
, it returned the permutations of (1 2 3)
! So you should now be able to write another function, permutations
, which makes use of thread-lists
to create permutations.
Note I don't know if this approach is anything like efficient and I would expect it not to be. It is, I think, fairly clear.