mat ← ##.pmat n                             ⍝ Permutation matrix of ⍳⍵.

[pmat]  takes an integer scalar [n] and returns a !n row matrix of the permutat-
ions of ⍳n.

Technical notes:

The  method  used  here  is  to take each item of ⍳n in turn and append all sub-
permutations of the remaining (n-1) items. This produces result items in ascend-
ing order. Thus, for any ⍵: {⍵≡⍳⍴⍵}⍋pmat ⍵.

The code looks like this:

    pmat←{                  ⍝ Permutation matrix of ⍳⍵.
        {                   ⍝ perms of ⍳⍵:
            1≥⍴⍵:↑,↓⍵       ⍝ short vector: done.
            ↑⍪/⍵,∘∇¨⍵∘~¨⍵   ⍝ items prefix sub-perms of remainder.
        }⍳⍵                 ⍝ permutations of identity perm.
    }

Perttu  Pakarinen suggests the following _much faster_ version. It produces rows
in non-ascending order but could easily be modified: {⍵[⍋⍵;]}.

    prm←{
        (⎕IO ⎕ML)←1 3
        (×\⍳⍵){0∊⍴⍺:⍵ ⋄ (r c)←⍴⍵
            (1↓⍺)∇(r/0,⍳c)⌽(⍺[1],c+1)⍴(↑⍴⍺),⍵}1 0⍴0
    }

For  large values of ⍵, the resulting permutation matrix takes a large amount of
workspace.  In  this  case, it might be better to apply an auxiliary function to
each permutation as it is generated. The following operator does the trick:

    perms←{                 ⍝ Apply ⍺⍺ to each perm of ⍳⍵
        ⍬ ⍺⍺{               ⍝ null accumulator
            1≥⍴⍵:⍺⍺ ⍺,⍵     ⍝ short tail: apply operand to perm
            (⍺∘,¨⍵)∇¨⍵∘~¨⍵  ⍝ transfer each tail item to head
        }⍳⍵                 ⍝ for initial vector.
    }

Roger Hui provides this even faster version:

    pmat2←{{,[⍳2]↑(⊂⊂⎕io,1+⍵)⌷¨⍒¨↓∘.=⍨⍳1+1↓⍴⍵}⍣⍵⍉⍪⍬}

translated from perm2 in http://www.jsoftware.com/jwiki/Essays/Permutations
itself a translation from APL.

John Niss Hansen's "perm" functions
-----------------------------------
John provides these functions, which produce a more structured result:

    ⎕io←0                                           ⍝ Using index origin 0

    perm1←{⍵=0:⍬ ⋄ ((⍳⍵)⌽⍵ ⍵⍴⍳⍵)[;0,1+∇ ⍵-1]}       ⍝ Recursive indexing

    ]display perm1¨ ⍳4
┌→─────────────────────────┐
│ ┌⊖┐ ┌→┐ ┌┌→──┐ ┌┌┌→────┐ │
│ │0│ ↓0│ ↓↓0 1│ ↓↓↓0 1 2│ │
│ └~┘ └~┘ ││   │ │││     │ │
│         ││1 0│ │││0 2 1│ │
│         └└~──┘ │││     │ │
│                │││     │ │
│                │││1 2 0│ │
│                │││     │ │
│                │││1 0 2│ │
│                │││     │ │
│                │││     │ │
│                │││2 0 1│ │
│                │││     │ │
│                │││2 1 0│ │
│                └└└~────┘ │
└∊─────────────────────────┘

    ⍝ Non-recursive from natural adress-box:

    permn←{i←⍳⍵  ⋄ p←(i∘~¨i),¨i ⋄ {⊃{⍵[⍺⊃p]}/⍵,⊂i}¨⍳1+i}

    ]display permn¨ ⍳4
┌→─────────────────────────────────────────────────────────────┐
│ ┌─────┐ ┌→────┐ ┌→────────────┐ ┌┌→────────────────────────┐ │
│ │ ┌⊖┐ │ │ ┌→┐ │ ↓ ┌→──┐ ┌→──┐ │ ↓↓ ┌→────┐ ┌→────┐ ┌→────┐ │ │
│ │ │0│ │ │ │0│ │ │ │0 1│ │1 0│ │ ││ │0 1 2│ │1 0 2│ │2 0 1│ │ │
│ │ └~┘ │ │ └~┘ │ │ └~──┘ └~──┘ │ ││ └~────┘ └~────┘ └~────┘ │ │
│ └∊────┘ └∊────┘ └∊────────────┘ ││ ┌→────┐ ┌→────┐ ┌→────┐ │ │
│                                 ││ │0 2 1│ │1 2 0│ │2 1 0│ │ │
│                                 ││ └~────┘ └~────┘ └~────┘ │ │
│                                 └└∊────────────────────────┘ │
└∊─────────────────────────────────────────────────────────────┘

    permh←{0≡⍵:⍬ ⋄ pe←{1=≢⍵:⍵ ⋄ ↑⍵∘{⍵(pe ⍺~⍵)}¨⍵} ⋄ pe ⍳⍵}     ⍝ As hierarchy

    ]display permh¨ ⍳4
┌→──────────────────────────────────┐
│ ┌⊖┐ ┌→┐ ┌→──────┐ ┌→────────────┐ │
│ │0│ │0│ ↓   ┌→┐ │ ↓   ┌→──────┐ │ │
│ └~┘ └~┘ │ 0 │1│ │ │ 0 ↓   ┌→┐ │ │ │
│         │   └~┘ │ │   │ 1 │2│ │ │ │
│         │   ┌→┐ │ │   │   └~┘ │ │ │
│         │ 1 │0│ │ │   │   ┌→┐ │ │ │
│         │   └~┘ │ │   │ 2 │1│ │ │ │
│         └∊──────┘ │   │   └~┘ │ │ │
│                   │   └∊──────┘ │ │
│                   │   ┌→──────┐ │ │
│                   │ 1 ↓   ┌→┐ │ │ │
│                   │   │ 0 │2│ │ │ │
│                   │   │   └~┘ │ │ │
│                   │   │   ┌→┐ │ │ │
│                   │   │ 2 │0│ │ │ │
│                   │   │   └~┘ │ │ │
│                   │   └∊──────┘ │ │
│                   │   ┌→──────┐ │ │
│                   │ 2 ↓   ┌→┐ │ │ │
│                   │   │ 0 │1│ │ │ │
│                   │   │   └~┘ │ │ │
│                   │   │   ┌→┐ │ │ │
│                   │   │ 1 │0│ │ │ │
│                   │   │   └~┘ │ │ │
│                   │   └∊──────┘ │ │
│                   └∊────────────┘ │
└∊──────────────────────────────────┘

Beside generating permutations, one can also decompose permutations into cycles
and also determine the sign of a permutation.

    ⎕IO←0           ⍝ using index origin 0

    permcycles←{    ⍝ Find cycles of a permutation of the vector ⍳≢⍵
        lng←≢perm←⍵
        normalize←{(⍵⍳⌊/⍵)⌽⍵}                 ⍝ Shift cycle so smallest element first
        ∪normalize∘∪¨↓⍉↑{perm[⍵]}\lng/⊂perm   ⍝ Scan apply the permutation lng times
                                              ⍝ and retain unique cycles
    }

    cyclesign←{     ⍝ Sign of permutation cycles
        ⊃(1 ¯1)[⊃2|+/¯1+⍴¨⍵]
    }

And from here we easily get:

    permsign ← cyclesign∘permcycles

For the lovers of recursion we could also write permcycles as:

    permcycles←{⍝ Find cycles of a permutation of the vector ⍳≢⍵
        lng←≢perm←⍵                         ⍝ Local variables
        res←⍬                               ⍝ Initial result vector
        cycles←{                            ⍝ Recursive finding cycles
            ⍬≡⍵:⍬
            res,←⊂c←∪{perm[⍵]}\lng/⊃⍵       ⍝ Follow first element through its cycle elements, append cycle to result
            ∇ ⍵~c                           ⍝ Continue with the rest
        }
        dumy←cycles perm                    ⍝ Activate the process
        {(⍵⍳⌊/⍵)⌽⍵}¨res                     ⍝ Result as side-effect, Normalized by shift smallest element to first position
    }

I will finish this with 2 more non-recursive permutation generators, that funnily
enough both produce the same reult.

First, a semi-oneliner for the rich in computer resources:

    permz←{all←↓⍉(⍵/⍵)⊤⍳⍵*⍵ ⋄ ↑(∧/¨(⊂⍳⍵)∊¨all)/all}   ⍝ Select ⍵-digit numbers in ⍵-radix with ⍵ different digits

Secondly, the same normal sequence done by iterative swapping of tail elements.

    permn←{     ⍝ Permutations of order ⍵, ⎕io←0    ⍝ NON recursive
        bas←⌽⍳⍵                                     ⍝ Basic vector, initialy reversed-permutated
        swaps←(⊂⍳⍵){(⍵↑⍺),⌽⍵↓⍺}¨⌽⍳⍵+1               ⍝ Tail-swaps as the basic permutaions
        drumbeat←⊃+/(!⍵)⍴¨(!⍳⍵)↑¨1                  ⍝ The sequence of swaps
        ↑{##.bas←##.bas[⍵⊃swaps]}¨drumbeat          ⍝ Each element calculated from previous, with a trace of bas
   }

    ]display permz¨⍳4                               ⍝ Same as permn
┌→──────────────────────┐
│ ┌⊖┐ ┌→┐ ┌→──┐ ┌→────┐ │
│ ↓0│ ↓0│ ↓0 1│ ↓0 1 2│ │
│ └─┘ └─┘ │1 0│ │0 2 1│ │
│         └───┘ │1 0 2│ │
│               │1 2 0│ │
│               │2 0 1│ │
│               │2 1 0│ │
│               └─────┘ │
└───────────────────────┘

    ]display ⍴¨ permz¨⍳4
┌→────────────────────────┐
│ ┌→──┐ ┌→──┐ ┌→──┐ ┌→──┐ │
│ │1 0│ │1 1│ │2 2│ │6 3│ │
│ └───┘ └───┘ └───┘ └───┘ │
└─────────────────────────┘

Examples:

      pmat 3                            ⍝ 3-perms.
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

      {⍵[pmat⍴⍵]}'tic' 'tac' 'toe'      ⍝ Perms of nested vector.
 tic  tac  toe
 tic  toe  tac
 tac  tic  toe
 tac  toe  tic
 toe  tic  tac
 toe  tac  tic

      4 3 2⍴↓{⍵[pmat⍴⍵]}'abcd'          ⍝ Folded perms of simple 4-vector.
 abcd  abdc
 acbd  acdb
 adbc  adcb

 bacd  badc
 bcad  bcda
 bdac  bdca

 cabd  cadb
 cbad  cbda
 cdab  cdba

 dabc  dacb
 dbac  dbca
 dcab  dcba

      ⍴pmat 10                          ⍝ !⍵ rows.
3628800 10

      display∘pmat¨2 1 0                ⍝ Limiting cases
 ┌→──┐  ┌→┐  ┌⊖┐
 ↓1 2│  ↓1│  ↓0│
 │2 1│  └~┘  └~┘
 └~──┘

      (!0 to 5) ≡ ≢∘pmat¨0 to 5         ⍝ Result lengths.
1
                                        ⍝ Rows of the permutation matrix form
      {⍵⍳⍵∘.{⍺⊃¨⊂⍵}⍵}↓pmat 3            ⍝ a group under ⊃¨∘⊂ with identity ⍳⍵.
1 2 3 4 5 6
2 1 4 3 6 5
3 5 1 6 2 4
4 6 2 5 1 3
5 3 6 1 4 2
6 4 5 2 3 1

    ⎕∘← perms 3                         ⍝ show each permutation.
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1

See also: cmat

Back to: contents

Back to: Workspaces