# Featured Algorithms: permutations

## General attributes

- All functions in slippery-chicken that use random default to a fixed seed.
- Random operations return the same results each time they are started
  (on the same Lisp). 
- Most have options to reset the seed or not use a fixed seed.

----

## Permutations

### permutations

- Systematically produce a list of all possible permutations of a set of
  consecutive integers beginning with zero. 
- The order of the permutations will be the same each time the function is
  called. 

<!-- end list -->

    (permutations 4)

    =>
    ((0 1 2 3) (1 0 2 3) (0 2 1 3) (2 0 1 3) (1 2 0 3) (2 1 0 3) (0 1 3 2)
     (1 0 3 2) (0 3 1 2) (3 0 1 2) (1 3 0 2) (3 1 0 2) (0 2 3 1) (2 0 3 1)
     (0 3 2 1) (3 0 2 1) (2 3 0 1) (3 2 0 1) (1 2 3 0) (2 1 3 0) (1 3 2 0)
     (3 1 2 0) (2 3 1 0) (3 2 1 0))

----

### inefficient-permutations 

- Return a shuffled, non-systematic list of all possible permutations of a  
 set of consecutive integers beginning with zero.
- keyword arguments:
     - :max. (integer). Maximum number of permutations to return.
     - :skip. (integer). Number of permutations to skip.
         - Only really useful with fixed seed randomness
     - :fix. (`T` or `NIL`). `T` = shuffle with the same (fixed) random seed.

<!-- end list -->

    (inefficient-permutations 4 :max 7 :skip 2 :fix t)

    => ((2 0 3 1) (1 0 2 3) (1 2 3 0) (0 2 3 1) (2 1 0 3))

- E.g. [inefficient-permutations violin mini]

----

### permutate

- Systematically produce a list of all possible permutations of an original
 list of elements of any type.
- *NB: These lists get very long very fast!*
    - *List of 5 elements returns new list of 120; 6 returns 720!*
    - Original lists >8 elements results in permutations being written to a
      file.

<!-- end list -->

    (permutate '(a b c d))

    => ((A B C D) (B A C D) (A C B D) (C A B D) (B C A D) (C B A D) (A B D C)
        (B A D C) (A D B C) (D A B C) (B D A C) (D B A C) (A C D B) (C A D B)
        (A D C B) (D A C B) (C D A B) (D C A B) (B C D A) (C B D A) (B D C A)
        (D B C A) (C D B A) (D C B A))

----

### inefficiently-permutate 

- Return a shuffled, non-systematic list of all possible permutations of an
 original list of elements of any type.
- New list returned as flat list by default.
- *NB: These lists get very long very fast!*
    - Original lists >8 elements results in permutations being written to a
      file.
- keyword arguments:
     - :max. (integer). Maximum number of permutations to return.
     - :skip. (integer). Number of permutations to skip.
     - :fix. (`T` or `NIL`). `T` = shuffle with the same (fixed) random seed.
     - :sublists. (`T` or `NIL`). `T` = return as list of lists.

<!-- end list -->

    (inefficiently-permutate '(a b c d) :max 7 :skip 2 :fix t)

    => (C A D B B A C D B C D A A C D B C B A D)

----

### shuffle 

- Create a random ordering of a given list or a segment of a given list.
- keyword arguments:
    - :start. (integer, 0-based). First element of list to be shuffled.
    - :end. (integer, 0-based). Last element of list to be shuffled.
    - :copy. (`T` or `NIL`). `T` = make copy of list (non-destructive).
    - :fix. (`T` or `NIL`). `T` = shuffle with the same (fixed) random seed.
    - :reset. (`T` or `NIL`) `T` = reset random state.

<!-- end list -->

    (shuffle '(1 2 3 4 5 6 7) :start 1 :end 5 :fix t :reset t)

    => (1 5 4 3 2 6 7)

----

### multi-shuffle

- Apply the `shuffle` function a specified number of times to a specified list.
- keyword arguments:
    - :start. (integer, 0-based). First element of list to be shuffled.
    - :end. (integer, 0-based). Last element of list to be shuffled.
    - :copy. (`T` or `NIL`). `T` = make copy of list (non-destructive).
    - :fix. (`T` or `NIL`). `T` = shuffle with the same (fixed) random seed.
    - :reset. (`T` or `NIL`) `T` = reset random state.

<!-- end list -->

    (multi-shuffle '(1 2 3 4 5 6 7) 11 :start 1 :end 5 :fix t :reset t)

----

### multi-shuffle-with-perms

- Return one permutation of a shuffled version of the specified list.
- 2nd argument: number consecutive shuffles to be collected in the list from
   which the resulting permutation is selected.
- Always uses a fixed random seed.

<!-- end list -->

    (multi-shuffle-with-perms '(0 1 2 3 4) 7)

    => (3 1 4 2 0)

----

### move-repeats

- Move, when possible, any elements of a list that are repeated consecutively.
    - Only moves to the right.
    - Moves to first place where no repeat is created.
- When no non-repeating place can be found, the element is moved to the end.
- Can be applied to simple lists and lists with sublists.
- If used with sublists, the last element of each sublist is checked for
 repetition with the first element of the next.

<!-- end list -->

    (move-repeats '(1 2 3 3 4 5 6 7 8 8 9 10))

    => (1 2 3 4 3 5 6 7 8 9 8 10)

    (move-repeats '((a b c) (c a b) (c a b) (d e f) (a b c) (g h i)))

    => ((A B C) (D E F) (C A B) (C A B) (A B C) (G H I))

----

### random-rep

- Return a random non-negative number that is < specified value. 
- Optional argument allows for the random state to be reset.

<!-- end list -->

    (loop repeat 10 collect (random-rep 5))

    => (2 4 0 4 4 2 1 3 2 4)

    (loop repeat 10 collect (random-rep 5 t))

    => (3 3 3 3 3 3 3 3 3 3)

----

### Exercise: PERMUTATIONS

See http://michael-edwards.org/sc/workshop-exercises.lsp

