Skip to content

Instantly share code, notes, and snippets.

@tallakt
Last active August 27, 2015 08:37
Show Gist options
  • Save tallakt/148d93941cf653d88e8d to your computer and use it in GitHub Desktop.
Save tallakt/148d93941cf653d88e8d to your computer and use it in GitHub Desktop.
defmodule XStream do
@doc """
Returns a stream of all permutations of the given collection.
The count parameter will limit the number of elements, all are returned
by default
## Examples
iex> XStream.permutations 1..3 |> Enum.to_list
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]]
"""
def permutations(enumerable, count) when count >= 0 do
enumerable |> Enum.to_list |> do_permutations(count)
end
def permutations(enumerable) do
enumerable |> Enum.to_list |> do_permutations(-1)
end
defp do_permutations([], _), do: []
defp do_permutations(_, 0), do: []
defp do_permutations(list, count) do
list
|> elements_partitioned
|> Stream.flat_map(fn {element, the_rest} ->
case {count, the_rest} do
{_, []} ->
[[element]]
{1, _} ->
[[element]]
_ ->
the_rest |> do_permutations(count - 1) |> Stream.map(fn p -> [element | p] end)
end
end)
end
defp elements_partitioned(enumerable) do
enumerable
|> Stream.map fn element ->
other = enumerable |> Enum.reject(fn x -> x == element end)
{element, other}
end
end
end
defmodule XEnum do
@doc """
Returns a stream of all permutations of the given collection.
## Examples
iex> permutations = XEnum.permutations 1..3
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]]
"""
def permutations(enumerable, count) when count >= 0 do
enumerable |> Enum.to_list |> do_permutations(count)
end
def permutations(enumerable) do
enumerable |> Enum.to_list |> do_permutations(-1)
end
defp do_permutations([], _), do: []
defp do_permutations(_, 0), do: []
defp do_permutations(list, count) do
list
|> elements_partitioned
|> Enum.flat_map(fn {element, the_rest} ->
case {count, the_rest} do
{_, []} ->
[[element]]
{1, _} ->
[[element]]
_ ->
the_rest
|> do_permutations(count - 1)
|> Enum.map(fn p -> [element | p] end)
end
end)
end
defp elements_partitioned(enumerable) do
enumerable
|> Enum.map fn element ->
other = enumerable |> Enum.reject(fn x -> x == element end)
{element, other}
end
end
end
XEnum.permutations(1..3) |> Enum.to_list |> IO.inspect
XEnum.permutations(1..4, 2) |> Enum.to_list |> IO.inspect
Test.permutations(1..3) |> Enum.to_list |> IO.inspect
Test.permutations(1..3) |> Enum.take(3) |> IO.inspect
# XStream.permutations(1..2) |> Enum.to_list |> IO.inspect
# XStream.permutations(1..4, 2) |> Enum.to_list |> IO.inspect
# XStream.permutations(1..3) |> Enum.take(3) |> IO.inspect
# XStream.permutations(1..40) |> Enum.take(3) |> IO.inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment