エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

組合わせ論の順列

もうちょっと簡単に書けるんじゃないかという気がするのですが、とりあえず忘れないうちに。

defmodule Combinatorics do
  def permutation(list), do: permutation(list, Enum.count(list))
  def permutation(_, 0), do: [[]]
  def permutation(list, n) do
    list
    |> Enum.flat_map(fn elem ->
      list
      |> List.delete(elem)
      |> permutation(n - 1)
      |> Enum.map(&[elem | &1])
    end)
  end
end
$ iex
iex(1)> c "combinatorics.ex"
[Combinatorics]
iex(2)> Combinatorics.permutation([1,2,3,4])
[
  [1, 2, 3, 4],
  [1, 2, 4, 3],
  [1, 3, 2, 4],
  [1, 3, 4, 2],
  [1, 4, 2, 3],
  [1, 4, 3, 2],
  [2, 1, 3, 4],
  [2, 1, 4, 3],
  [2, 3, 1, 4],
  [2, 3, 4, 1],
  [2, 4, 1, 3],
  [2, 4, 3, 1],
  [3, 1, 2, 4],
  [3, 1, 4, 2],
  [3, 2, 1, 4],
  [3, 2, 4, 1],
  [3, 4, 1, 2],
  [3, 4, 2, 1],
  [4, 1, 2, 3],
  [4, 1, 3, 2],
  [4, 2, 1, 3],
  [4, 2, 3, 1],
  [4, 3, 1, 2],
  [4, 3, 2, 1]
]
iex(3)> Combinatorics.permutation('abc')    
['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
iex(4)> Combinatorics.permutation([1, 2, 3])   
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
iex(5)> Combinatorics.permutation([1, 2, 3], 1)
[[1], [2], [3]]
iex(6)> Combinatorics.permutation([1, 2, 3], 2)
[[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
iex(7)> Combinatorics.permutation([1, 2, 3], 3)
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
iex(8)> Combinatorics.permutation([1, 2, 3], 4)
[]