Search code examples
algorithmgo

Generate all permutations in go


I am looking for a way to generate all possible permutations of a list of elements. Something similar to python's itertools.permutations(arr)

permutations ([])
[]

permutations ([1])
[1]

permutations ([1,2])
[1, 2]
[2, 1]

permutations ([1,2,3])
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

With the difference that I do not care whether permutations would be generated on demand (like a generator in python) or all together. I also do not care whether they will be lexicographically sorted. All I need is to somehow get these n! permutations.


Solution

  • There are a lot of the algorithms that generate permutations. One of the easiest I found is Heap's algorithm:

    It generates each permutation from the previous one by choosing a pair of elements to interchange.

    The idea and a pseudocode that prints the permutations one after another is outlined in the above link. Here is my implementation of the algorithm which returns all permutations

    func permutations(arr []int)[][]int{
        var helper func([]int, int)
        res := [][]int{}
    
        helper = func(arr []int, n int){
            if n == 1{
                tmp := make([]int, len(arr))
                copy(tmp, arr)
                res = append(res, tmp)
            } else {
                for i := 0; i < n; i++{
                    helper(arr, n - 1)
                    if n % 2 == 1{
                        tmp := arr[i]
                        arr[i] = arr[n - 1]
                        arr[n - 1] = tmp
                    } else {
                        tmp := arr[0]
                        arr[0] = arr[n - 1]
                        arr[n - 1] = tmp
                    }
                }
            }
        }
        helper(arr, len(arr))
        return res
    }
    

    and here is an example of how to use it (Go playground):

    arr := []int{1, 2, 3}
    fmt.Println(permutations(arr))
    [[1 2 3] [2 1 3] [3 2 1] [2 3 1] [3 1 2] [1 3 2]]
    

    One thing to notice that the permutations are not sorted lexicographically (as you have seen in itertools.permutations). If for some reason you need it to be sorted, one way I have found it is to generate them from a factorial number system (it is described in permutation section and allows to quickly find n-th lexicographical permutation).

    P.S. you can also take a look at others people code here and here