euler_ex/lib/euler/combinatorics/permutations.ex

22 lines
746 B
Elixir

defmodule Euler.Combinatorics.Permutations do
defp index_at(_, 0, acc), do: acc |> Enum.reverse()
defp index_at(n, remaining, acc) do
blk_size = Euler.Algebra.fact(remaining - 1)
index_at(rem(n, blk_size), remaining - 1, [ div(n, blk_size) | acc ])
end
@doc """
Generates the n-th indexed permutation in the lexicographically ordered list of `remaining` digits.
"""
def index_at(n, remaining) do
index_at(n, remaining, [])
|> translate(remaining)
end
defp translate(a, n) when is_number(n), do: translate(a, (0..(n-1)) |> Enum.to_list)
defp translate(_, []), do: []
defp translate([next | rest], allowed) do
[ (allowed |> Enum.at(next)) | translate(rest, allowed |> List.delete_at(next)) ]
end
end