Nx4 Table of randi(1,M) so that the columns are not equal and each number only repeats P times

17 次查看(过去 30 天)
I need to create an N x 4 table array that where each column contains random integers between 1 and M. However the number of times each of the random number repeats in a single column cannot exceed a specific number P and must also not equal the value in the preceeding column.
Here is some code setting up the first two columns.
c1 = {'A';'B';'C';'D';...
'E';'F';'G';'H';...
'I';'J';'K';'L';'M'};
M = 4;
N = 13;
P = [4,3,4,3]; % 1, 2, 3, 4
c2 = [1;3;2;4;3;4;1;4;3;1;2;3;1];
disp(table(c1,c2,'VariableNames',{'Names','Arbitrary'}))
Names Arbitrary _____ _________ {'A'} 1 {'B'} 3 {'C'} 2 {'D'} 4 {'E'} 3 {'F'} 4 {'G'} 1 {'H'} 4 {'I'} 3 {'J'} 1 {'K'} 2 {'L'} 3 {'M'} 1
Notice, I chose the numbers between 1 and 4 (M = 4) arbitrarily for the second column. This means ...
  • P = 4 for 1.
  • P = 3 for 2.
  • P = 4 for 3.
  • P = 3 for 4.
To make things easier, I want to maintain this arrangement of P for each integer in the next column.
I think this question helps me generate the random numbers in the third column, but I am not sure how to make sure there are P = 4 1's, P = 3 2's etc.
c3 = zeros(N,1);
for i=1:N
vv = setdiff(1:M,c2(i));
r = randi(M-1,1);
c3(i) = vv(r);
end
disp(table(c1,c2,c3,'VariableNames',...
{'Names','Arbitrary','Third Column'}))
Names Arbitrary Third Column _____ _________ ____________ {'A'} 1 2 {'B'} 3 1 {'C'} 2 1 {'D'} 4 3 {'E'} 3 1 {'F'} 4 3 {'G'} 1 4 {'H'} 4 3 {'I'} 3 4 {'J'} 1 2 {'K'} 2 3 {'L'} 3 1 {'M'} 1 4
P1 = sum(c3==1)
P1 = 4
P2 = sum(c3==2)
P2 = 2
P3 = sum(c3==3)
P3 = 4
P4 = sum(c3==4)
P4 = 3
So now I have the third column of random integers between 1 and M excluding c2(i) for every name, but I have no idea how to make sure the number of each integer follows the criteria set apart. The same problem will persist when I make the fourth column where the value cannot equal that in c3(i).
Aside from generating the random numbers, I'm stuck.
  1 个评论
Dyuman Joshi
Dyuman Joshi 2023-1-5
So if I am understanding correct, if the distribution in 2nd column is
4 1's
3 2's
4 3's
2 4's
The distribution in 3rd column should not equal to any of the values of above, the # of repetitions of 1-4 must be different. (Similar for 4th column as well, not matching with 2nd or 3rd)
And you want this for 3 columns (2nd, 3rd and 4th)?
Are the values of M, N and P fixed for this problem? (4, 13 and the [4 3 4 3] respectively)

请先登录,再进行评论。

回答(1 个)

Jiri Hajek
Jiri Hajek 2023-1-5
编辑:Jiri Hajek 2023-1-5
Hi, I think you can use an algorithm which essentially mimics your prescription like the following code snippet. There is just the first column, but it is straightforward to extend to cover all four. Note that depending on the values of N, M and P, it can happen quite easily that the generation of the matrix will fail.
% Definitions
N = 30;
M = 20;
P = 10;
% Is solution possible?
if M*P <= N
error('solution is not possible');
end
%% First column
firstColumn = zeros(N,1); % First column - just random numbers below M
availableNumbers = 1:M; % unique integers below M == [1:M]
while nnz(firstColumn) < N
% check if there are still available numbers
if isempty(availableNumbers)
disp(firstColumn)
error('first column generation error: no available numbers, %d unassigned positions',nnz(~firstColumn))
end
% choose one of the available numbers and eliminate it from future choices
idx = randi(length(availableNumbers));
xi = availableNumbers(idx);
availableNumbers(idx) = [];
% choose the number of occurences
Pxi = randi(min(P,N-nnz(firstColumn)));
% choose random indexes to place the selected xi
for i = 1:Pxi
ifree = find(firstColumn == 0);
nfree = length(ifree);
inew = randi(nfree);
firstColumn(ifree(inew)) = xi;
end
end
disp(firstColumn)

产品


版本

R2021b

Community Treasure Hunt

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

Start Hunting!

Translated by