Go言語でスライスの要素の順列、組み合わせを与える

これって組み込み関数がないのですかねえ...

順列。コード。
permutation.go

package main
import "fmt"

//スライスの 位置 i の要素を除いたスライスを返す(arを破壊しないようコピーしている)
func remove(ar []int, i int) []int {
    tmp := make([]int, len(ar))
    copy(tmp, ar)
    return append(tmp[0:i], tmp[i + 1:]...)
}

func permutation(ar []int) [][]int {
    var result [][]int
    if len(ar) == 1 {return append(result, ar)}
    for i, a := range ar {
        for _, b := range permutation(remove(ar, i)) {
            result = append(result, append([]int{a}, b...))
        }
    }
    return result
}

func main() {
    fmt.Println(permutation([]int{50, 2, 1, 9}))
}

結果。

[[50 2 1 9] [50 2 9 1] [50 1 2 9] [50 1 9 2] [50 9 2 1] [50 9 1 2] [2 50 1 9]
 [2 50 9 1] [2 1 50 9] [2 1 9 50] [2 9 50 1] [2 9 1 50] [1 50 2 9] [1 50 9 2]
 [1 2 50 9] [1 2 9 50] [1 9 50 2] [1 9 2 50] [9 50 2 1] [9 50 1 2] [9 2 50 1]
 [9 2 1 50] [9 1 50 2] [9 1 2 50]]

 

ちなみにこれは Ruby では

def permutation(ar)
  result = []
  return [ar] if ar.size == 1
  ar.each_with_index do |a, i|
    permutation(ar[0, i] + ar[i + 1..-1]).each do |b|
      result += [[a] + b]
    end
  end
  result
end

p permutation([50, 2, 1, 9])

で同等。あるいは組み込み関数を使って

p [50, 2, 1, 9].permutation.to_a

でおしまい。
 

素数を指定した順列、組み合わせ

package main
import "fmt"

func remove(ar []int, i int) []int {
    tmp := make([]int, len(ar))
    copy(tmp, ar)
    return append(tmp[0:i], tmp[i + 1:]...)
}

func permutation_full(ar []int) [][]int {
    var result [][]int
    if len(ar) == 1 {return append(result, ar)}
    for i, a := range ar {
        for _, b := range permutation_full(remove(ar, i)) {
            result = append(result, append([]int{a}, b...))
        }
    }
    return result
}

//順列
func permutation(ar []int, n int) (result [][]int) {
    for _, a := range combination(ar, n) {
        result = append(result, permutation_full(a)...)
    }
    return
}

//組み合わせ
func combination(ar []int, n int) (result [][]int) {
    if n <= 0 || len(ar) < n {return}
    if n == 1 {
        for _, a := range ar {
            result = append(result, []int{a})
        }
    } else if len(ar) == n {
        result = append(result, ar)
    } else {
        for _, a := range combination(ar[1:], n - 1) {
            result = append(result, append([]int{ar[0]}, a...))
        }
        result = append(result, combination(ar[1:], n)...)
    }
    return
}

func main() {
    fmt.Println(combination([]int{50, 2, 1, 9}, 3))
    fmt.Println(permutation([]int{50, 2, 1, 9}, 3))
}

組み合わせの場合が結構複雑になったのだけれど、もっといいやり方はないかな。
結果。

[[50 2 1] [50 2 9] [50 1 9] [2 1 9]]

[[50 2 1] [50 1 2] [2 50 1] [2 1 50] [1 50 2] [1 2 50] [50 2 9] [50 9 2]
 [2 50 9] [2 9 50] [9 50 2] [9 2 50] [50 1 9] [50 9 1] [1 50 9] [1 9 50]
 [9 50 1] [9 1 50] [2 1 9] [2 9 1] [1 2 9] [1 9 2] [9 2 1] [9 1 2]]

 
[]int はお好みの型でどうぞ。Go は [[]] という配列は作れないのだな。ああ、[]interface{}{[]int{}} とかはできるか。

しかしこれ、C でやったら大変そう。どうやってやるのだろう。