生成具有受控输出的集合的排列?

时间:2015-05-01 16:23:19

标签: matlab permutation

有没有一种简单的方法可以获得集合的前x个排列?

例如,具有5个字符{a,b,c,d,e}的集合将具有

5 * 5 * 5 * 5 * 5 = 3125排列输出

(允许重复,例如{a,a,a,a,a})

但我想只有前100个值,例如

4 个答案:

答案 0 :(得分:2)

您可以使用WHERE获取集合P = perms(S)的所有排列,然后如果您想要100,则可以S

对于随机,您可以使用P(1:100,:)

如果您知道需要更具体地说明排列,那么您可以将P(randperm(size(P,1),100),:)permute参数一起使用 - http://uk.mathworks.com/help/matlab/ref/permute.html

答案 1 :(得分:2)

生成所有排列的一种方法'当时按字典顺序排列,不必将它们全部存储在记忆中:

function permute_chars(alphabet, nword, nmax)

if nargin < 3  % default to displaying all, this can be a huge number!
    nmax = nchar^nword;
end

nchar = length(alphabet);
ind = zeros(1, nword);
i = 0;

while i < nmax
    % just printing the permutaions, edit according to your needs
    disp(cell2mat(alphabet(ind + 1))); 

    % calculate next indices, classic elementary school addition with carry
    ind(end) = ind(end) + 1;
    for j = nword:-1:2
        if ind(j) == nchar 
            ind(j) = 0;  % wrap around
            ind(j-1) = ind(j-1) + 1;  % carry
        end
    end     
    i = i + 1;
end

当然,我忘记了一些不起眼的功能,它可以用更少的行来实现它,但是这样写的很清楚它是如何工作的。快速测试:

>> alphabet = {'a', 'b', 'c', 'd', 'e'};
>> permute_chars(alphabet, 1)
a
b
c
d
e
>> permute_chars(alphabet, 2)
aa
ab
ac
ad
ae
ba
[... snip ...]
ed
ee

仅打印有限数量的排列:

>> permute_chars(alphabet, 5, 8)
aaaaa
aaaab
aaaac
aaaad
aaaae
aaaba
aaabb
aaabc

答案 2 :(得分:1)

要从数字1:n中选择100个随机唯一样本,并允许重复(替换采样),您可以使用randi或类似内容创建超过100 x n的列表随机样本,unique删除重复项,然后取前100个。

例如,使用randi

% from numbers 1:n, create 200 by n random matrix
sample_list = randi(n,[200, n]);
% remove duplicates
sample_list = unique(sample_list,'rows'); 
% you should probably error check here
% presuming there's >100 options left, take 100 of them
sample_list = sample_list(1:100,:);

sample_list将是一个数字矩阵,但如果需要,您可以轻松地将其用作其他内容的索引:

my_set = {'a','b','c','d','e'}; % 1 x 5 cell
my_permutes = my_set(sample_list); % 100 x 5 cell

这避免了必须计算每一个可能的选项,对于较大的n,这会成为问题。

答案 3 :(得分:1)

为了在您获得的排列范围内更灵活一些,您可以使用一个函数,在给定排列的情况下,该函数会在该系列中生成下一个排列。在这个实现中,即使输入排列超出范围,我也选择让排列回绕到第一个排列。

function newperm = nextPerm(oldperm, base)
   if any(oldperm >= base)
      newperm = zeros(1,numel(oldperm));
      return
   end
   idx = numel(oldperm);
   newperm = oldperm;
   while idx > 0
      newperm(idx) = newperm(idx) + 1;
      if newperm(idx) < base
         return;
      end
      newperm(idx) = 0;
      idx = idx - 1;
   end
end

排列元素从0开始(因此max元素是base-1)。

p = [4 4 4 4 4]
nextPerm(p, 5)
ans =

   0   0   0   0   0

p = [0 0 0 0 0]
nextPerm(p, 5)
ans =

   0   0   0   0   1

p = [3 4 1 0 2]
nextPerm(p, 5)
ans =

   3   4   1   0   3

p = [3 4 5 0 2] %// invalid value '5'
nextPerm(p, 5)
ans =

   0   0   0   0   0

要获得范围,只需通过循环输入:

myPerms = zeros(5);
myPerms(1,:) = [3 1 2 0 4];
for k = 2:5
   myPerms(k,:) = nextPerm(myPerms(k-1,:), size(myPerms,1));
end

myPerms =

   3   1   2   0   4
   3   1   2   1   0
   3   1   2   1   1
   3   1   2   1   2
   3   1   2   1   3

要将排列映射到您的字母表,只需将1添加到向量并将其用作索引:

alphabet = ['a', 'b', 'c', 'd', 'e'];
word = alphabet(myPerms(1,:)+1)

word = dbcae