permute with exact repeats

조회 수: 1 (최근 30일)
mark palmer
mark palmer 2023년 12월 12일
댓글: Dyuman Joshi 2023년 12월 13일
I'm trying to permute a comprehensive list of 3 elements, say [1 2 3]
over a 5-size array with at least 1 element included from the 3 element array. (I'd like it the result be general, so the variables might be 3 over 6, 4 over 7, etc.) Obviously I can do this by brute force but I'd prefer a more elegant solution.
The result would be
1 1 1 2 3
1 1 1 3 2
1 1 2 1 3
1 1 2 3 1
1 1 3 1 2
1 1 3 2 1
1 1 3 2 2
1 1 3 3 2
1 2 1 1 3
1 2 1 2 3
...
3 3 3 2 1

채택된 답변

Voss
Voss 2023년 12월 12일
Here's one way:
x = [1 2 3];
n = 5;
% generate a matrix M whose rows are all possible
% sets of n elements from x:
m = numel(x);
M = x(1+dec2base(0:m^n-1,m)-'0');
% remove rows of M that don't have each element
% of x at least once:
for ii = 1:m
M(~any(M == x(ii),2),:) = [];
end
disp(M)
1 1 1 2 3 1 1 1 3 2 1 1 2 1 3 1 1 2 2 3 1 1 2 3 1 1 1 2 3 2 1 1 2 3 3 1 1 3 1 2 1 1 3 2 1 1 1 3 2 2 1 1 3 2 3 1 1 3 3 2 1 2 1 1 3 1 2 1 2 3 1 2 1 3 1 1 2 1 3 2 1 2 1 3 3 1 2 2 1 3 1 2 2 2 3 1 2 2 3 1 1 2 2 3 2 1 2 2 3 3 1 2 3 1 1 1 2 3 1 2 1 2 3 1 3 1 2 3 2 1 1 2 3 2 2 1 2 3 2 3 1 2 3 3 1 1 2 3 3 2 1 2 3 3 3 1 3 1 1 2 1 3 1 2 1 1 3 1 2 2 1 3 1 2 3 1 3 1 3 2 1 3 2 1 1 1 3 2 1 2 1 3 2 1 3 1 3 2 2 1 1 3 2 2 2 1 3 2 2 3 1 3 2 3 1 1 3 2 3 2 1 3 2 3 3 1 3 3 1 2 1 3 3 2 1 1 3 3 2 2 1 3 3 2 3 1 3 3 3 2 2 1 1 1 3 2 1 1 2 3 2 1 1 3 1 2 1 1 3 2 2 1 1 3 3 2 1 2 1 3 2 1 2 2 3 2 1 2 3 1 2 1 2 3 2 2 1 2 3 3 2 1 3 1 1 2 1 3 1 2 2 1 3 1 3 2 1 3 2 1 2 1 3 2 2 2 1 3 2 3 2 1 3 3 1 2 1 3 3 2 2 1 3 3 3 2 2 1 1 3 2 2 1 2 3 2 2 1 3 1 2 2 1 3 2 2 2 1 3 3 2 2 2 1 3 2 2 2 3 1 2 2 3 1 1 2 2 3 1 2 2 2 3 1 3 2 2 3 2 1 2 2 3 3 1 2 3 1 1 1 2 3 1 1 2 2 3 1 1 3 2 3 1 2 1 2 3 1 2 2 2 3 1 2 3 2 3 1 3 1 2 3 1 3 2 2 3 1 3 3 2 3 2 1 1 2 3 2 1 2 2 3 2 1 3 2 3 2 2 1 2 3 2 3 1 2 3 3 1 1 2 3 3 1 2 2 3 3 1 3 2 3 3 2 1 2 3 3 3 1 3 1 1 1 2 3 1 1 2 1 3 1 1 2 2 3 1 1 2 3 3 1 1 3 2 3 1 2 1 1 3 1 2 1 2 3 1 2 1 3 3 1 2 2 1 3 1 2 2 2 3 1 2 2 3 3 1 2 3 1 3 1 2 3 2 3 1 2 3 3 3 1 3 1 2 3 1 3 2 1 3 1 3 2 2 3 1 3 2 3 3 1 3 3 2 3 2 1 1 1 3 2 1 1 2 3 2 1 1 3 3 2 1 2 1 3 2 1 2 2 3 2 1 2 3 3 2 1 3 1 3 2 1 3 2 3 2 1 3 3 3 2 2 1 1 3 2 2 1 2 3 2 2 1 3 3 2 2 2 1 3 2 2 3 1 3 2 3 1 1 3 2 3 1 2 3 2 3 1 3 3 2 3 2 1 3 2 3 3 1 3 3 1 1 2 3 3 1 2 1 3 3 1 2 2 3 3 1 2 3 3 3 1 3 2 3 3 2 1 1 3 3 2 1 2 3 3 2 1 3 3 3 2 2 1 3 3 2 3 1 3 3 3 1 2 3 3 3 2 1
  댓글 수: 3
mark palmer
mark palmer 2023년 12월 13일
Thanks both that was quick and very helpful!
Voss
Voss 2023년 12월 13일
You're welcome!

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Cris LaPierre
Cris LaPierre 2023년 12월 12일
I think this does what you are looking for.
v = 1:3;
% create all 5-digit possible combinations
T = table2array(combinations(v,v,v,v,v));
% Extract only those that contain a 3 numbers
idx = any(T==1,2) & any(T==2,2) & any(T==3,2);
T = T(idx,:)
T = 150×5
1 1 1 2 3 1 1 1 3 2 1 1 2 1 3 1 1 2 2 3 1 1 2 3 1 1 1 2 3 2 1 1 2 3 3 1 1 3 1 2 1 1 3 2 1 1 1 3 2 2
  댓글 수: 2
Adam Danz
Adam Danz 2023년 12월 13일
편집: Adam Danz 2023년 12월 13일
Great idea to use combinations (R2023a and later).
I fiddled with your solution a bit to make it flexibly receive any number of combinations.
v = 1:3;
n = 5;
% create all 5-digit possible combinations
in = repelem({v},1,n);
A = table2array(combinations(in{:}));
% Extract only those that contain a 3 numbers
c = arrayfun(@(x)any(ismember(A,x),2),v,'UniformOutput',false);
rm = ~all([c{:}],2);
A(rm,:) = []
A = 150×5
1 1 1 2 3 1 1 1 3 2 1 1 2 1 3 1 1 2 2 3 1 1 2 3 1 1 1 2 3 2 1 1 2 3 3 1 1 3 1 2 1 1 3 2 1 1 1 3 2 2
Dyuman Joshi
Dyuman Joshi 2023년 12월 13일
Nice approach @Cris LaPierre and @Adam Danz, but OP is working with R2022a, so they won't be able to utilize this.

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Logical에 대해 자세히 알아보기

제품


릴리스

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by