使用Erlang生成自定义排列

时间:2011-12-13 12:28:40

标签: recursion erlang stack permutation

注意:这是我以前的排列question的“续集”问题。

我想在Erlang中生成列表的所有排列,但我想在将它们添加到堆栈或存储在任何地方之前过滤掉一些排列。

我会根据一些自定义的临时规则过滤掉排列(让我们称之为“过滤器”)。

换句话说,我想生成一个大型列表的排列列表(50-300个元素),但我想在此过程中抛出大部分生成的排列(我知道全部数字)排列是N!)。

steenslag在Ruby中给了我一个很好的solution

res = [1,2,3,4].permutation(3).reject do |perm|
  perm.first.even? #Filter: if this line is true, the perm will be rejected
end

如何在Erlang中编写类似内容?

(我的Filter函数已经用Erlang编写了,所以我想做一些代码重用)。

顺便说一句,所需的Erlang解决方案能否“内在并行”?

2 个答案:

答案 0 :(得分:2)

您可以在构建后立即过滤排列。

只是一个例子,这个run()返回以偶数开头的[1,2,3,4]的所有排列。函数'check'(过滤结果)1)检查它是否是完全排列(结果长度==源列表长度),然后2)检查过滤条件(在我的情况下 - 第一个数字是偶数)。

run() ->
    perm([1,2,3,4],4).

perm([],_) ->
    [[]];
perm(L,N) -> [[H|T] || H <- L, T <- perm(L--[H],N), check( [H|T] ,N) ].

check(L,N) when length(L) < N -> true;
check([H|_],_) -> trunc(H/2) == H/2. .

答案 1 :(得分:1)

我为问题做了一个可能的实现:

-module(perm).

-export([pred_perms/2, pred/1]).

pred(L = [H | _T]) when H > 1 ->
    L;
pred(_L) ->
    [].

do_pred_perms([], _Pred) -> 
    [[]];
do_pred_perms(L, Pred)  -> 
    [Pred([H|T]) || H <- L, T <- do_pred_perms(L--[H], Pred)].

pred_perms(List, Pred) ->
    Res = do_pred_perms(List, Pred),
    lists:filter(fun(E) -> E =/= [] end, Res).

它使用空列表作为必须丢弃的列表的占位符。如果这是不可接受的,您可以将实现更改为不使用list compreension。

pred / 1函数只是一个用作谓词的示例函数。

希望这有帮助。