Erlang程式设计与问题解决/排列

维基教科书,自由的教学读本


排列,类似组合,有不可重复的排列和可重复的排列。排列是从一个列表取出指定数目的项目,对取出的相同项目来说,不同的顺序代表不同的排列。

排列函数的规格是

permutation ( N , List ) => [ permutation_1, permutation_2, ... ]

在列表 List 中,要取出 N 个,结果得到一列排列情况,每一种排列情况都包含 N 个项目。

不重复的排列[编辑]

从任何列表中取 0 个项目,结果只取得空列表。

permutation(0, _) ->
    [[]];

从空列表中,指定要取任何数目的项目,结果是空集合。

permutation(_, []) ->
    [];

接著是一般情况。要从列表取指定 N 项,做法是将每个项目轮流当做第一笔资料,每一个第一笔资料与其他 N-1 项排列情况结合。在此,列表型示 ( list comprehension ) 可以发挥功用。

permutation(N, Xs) ->
    [ [X|Rs] || X <- Xs,
                Rs <- permutation(N-1, Xs--[X]) ].

测试执行结果:

> test:permutation(3,[a,b,c,d]).
[[a,b,c],
 [a,b,d],
......

> test:permutation(5, [a,b,c]).
[]

> length(test:permutation(3, lists:seq(1,8))).
336

% 從 8 個數字中取 3 個,結果有 336 種組合

可重复的排列[编辑]

可重复的排列是取出每一项之后,又对原列表取剩下的 N-1 项。将上述不重复排列的程式第三句做一点修改,就会得到重复的排列。

permutation(N, Xs) ->
    [ [X|Rs] || X <- Xs,
                Rs <- permutation(N-1, Xs) ].

测试执行结果:

> test:permutation(2,[a,b,c]).
[[a,a],[a,b],[a,c],[b,a],[b,b],[b,c],[c,a],[c,b],[c,c]]

> test:permutation(5, [a,b,c]). 
[[a,a,a,a,a],
 [a,a,a,a,b],
......

> length(test:permutation(3, lists:seq(1,8))).
512

% 從 8 個數字中取 3 個可重複排列,結果有 512 種組合