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