独特的串珠项链组合

时间:2014-10-10 15:48:25

标签: matlab for-loop unique permutation

所以我正在编写一个程序来确定串珠项链的独特组合,但我似乎无法做到正确。规则是你不能向前和向后使用相同的项链,并且你不能拥有相同的项链,其中一个珠子滑到另一端。我附上了一些照片来澄清。

我为它编写了代码,我认为我已经实现了我想要做的事情,但它没有正常工作。

n = [1 2 3 4 2 4];
% green = 1
% blue = 2
% yellow = 3
% red = 4

p = perms(n);
total = max(size(p));
for i = 1:max(size(p))
    q = p;
    q(i) = [];
    for j = 1:max(size(q))
        if isequal(p(i),fliplr(q(j)))
            total = total - 1;
        elseif isequal(p(i),circshift(q(j),[1,1]))
            total = total - 1;
        elseif isequal(p(i),circshift(q(j),[length(q(j))-1,length(q(j))-1]))
            total = total - 1;
        end
        disp(total)
    end
end

从逻辑上讲,这对我来说很有意义,但我可能会疯狂。

2 个答案:

答案 0 :(得分:1)

如果问题规模很小,您可以对所有比较进行矢量化(使用bsxfun):

n = [1 2 3 4 2 4];
%// green = 1
%// blue = 2
%// yellow = 3
%// red = 4

N = numel(n);
p = perms(n).'; %'// generate all permutations

p2 = NaN([size(p) N+1]); %// this will store permutations with flips and shifts
p2(:,:,1) = p; %// original
p2(:,:,2) = flipud(p); %// flips
for k = 1:N-1
    p2(:,:,2+k) = circshift(p,k); %// circular shifts
end

eqElem = bsxfun(@eq, p, permute(p2, [1 4 2 3]));
eqMat = squeeze(any(all(eqElem, 1), 4)); %// 1 if equal
remove = any(tril(eqMat, -1), 1); %// remove permutations that are "similar"
%// to a previous one, where "similar" means "equal up to circular shifts or
%// flips"
result = p(:,~remove).'; %'// all valid arrangements; one per row
resultNum = size(result, 1); %// number of arrangements

结果:

result =
     1     3     2     2     4     4
     1     3     2     4     4     2
     1     3     2     4     2     4
     1     3     4     2     2     4
     1     3     4     2     4     2
     1     3     4     4     2     2
     1     2     3     2     4     4
     1     2     3     4     2     4
     1     2     3     4     4     2
     1     2     2     3     4     4
     1     2     2     4     4     3
     1     2     2     4     3     4
     1     2     4     3     2     4
     1     2     4     3     4     2
     1     2     4     2     3     4
     1     2     4     2     4     3
     1     2     4     4     2     3
     1     2     4     4     3     2
     1     4     4     3     2     2
     1     4     4     2     2     3
     1     4     4     2     3     2
     1     4     3     4     2     2
     1     4     3     2     2     4
     1     4     3     2     4     2
     1     4     2     3     2     4
     1     4     2     3     4     2
     1     4     2     2     3     4
     1     4     2     2     4     3
     1     4     2     4     2     3
     1     4     2     4     3     2

resultNum =
    30

答案 1 :(得分:0)

你应该在任何循环之前做p = unique(p,'rows')。要了解原因,请在命令行中调用perms([1 1 1])

这里有一些问题:

1)p,perms,是一个2D矩阵,所以要获得每个perm,你需要p(i,:)来获取行。 p(i)只是一个数字。

2)您没有从列表中删除错误的答案,因此您将对其进行两次检查。例如,假设列表中的第一个是[1 2 3 4 2 4];,第二个是[4 2 4 3 2 1];fliplr检查会将这两种组合进行两次比较,一次是在第一次循环中,一次是在第二次循环中。

3)如果你想确保排除任何旋转的排列(不仅仅是移动一个珠子),你还需要更多的旋转。

请再次使用ismember rows选项将单行(例如您要检查的行的翻转版本)与整个矩阵进行比较。