How can I get permutations of a list in Elixir?
Eg, for [\"a\", \"b\", \"c\"], I would expect:
# [[\"a\", \"b\", \"c\"], [\"a\", \"c\",
I’d put this code here for the sake of discoverability.
defmodule P do
defmacro permutations(l, n) do
clause =
fn i -> {:<-, [], [{:"i#{i}", [], Elixir}, l]} end
return =
Enum.map(1..n, fn i -> {:"i#{i}", [], Elixir} end)
Enum.reduce(1..n, return, fn i, acc ->
{:for, [], [clause.(i), [do: acc]]}
end)
end
end
defmodule T do
require P
def permute3(list), do: P.permutations(list, 3)
end
It uses plain AST to return the nested list comprehensions.
T.permute3 ~w|a b|
#⇒ [
# [[["a", "a", "a"], ["b", "a", "a"]],
# [["a", "b", "a"], ["b", "b", "a"]]],
# [[["a", "a", "b"], ["b", "a", "b"]],
# [["a", "b", "b"], ["b", "b", "b"]]]
# ]
It would require more effort to make it possible to pass n through as a parameter, because of early Range expansion, but it’s still doable.