Nx4 Table of randi(1,M) so that the columns are not equal and each number only repeats P times
2 views (last 30 days)
Show older comments
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'}))
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'}))
P1 = sum(c3==1)
P2 = sum(c3==2)
P3 = sum(c3==3)
P4 = sum(c3==4)
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 Comment
Dyuman Joshi
on 5 Jan 2023
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)
Answers (1)
Jiri Hajek
on 5 Jan 2023
Edited: Jiri Hajek
on 5 Jan 2023
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)
0 Comments
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!