Random matrix with no repeats in rows and columns.

11 visualizaciones (últimos 30 días)
Francisco Boudagh
Francisco Boudagh el 25 de Nov. de 2021
Editada: Image Analyst el 26 de Nov. de 2021
So I have generated a random matrix with dimensions 10x15 with values between 2 and 18 with step length 2.
Simple code:
candidates = 2:2:18;
idx = randi(numel(candidates), 10, 15);
M = candidates(idx)
So my questions is how do I do to never get a value above, under or next to the same value. As the ones I have marked with red in the picture.
  5 comentarios
Jan
Jan el 25 de Nov. de 2021
@Francisco Boudagh: So there are much more matrices, but cyclist's solution is one of the valid possibilities, isn't it?
the cyclist
the cyclist el 25 de Nov. de 2021
@Francisco Boudagh, I was just giving a single counter-example to dpb's concern that a valid solution might not even exist. I was not trying to solve your question.

Iniciar sesión para comentar.

Respuesta aceptada

Jan
Jan el 25 de Nov. de 2021
Editada: Jan el 26 de Nov. de 2021
Create the matrix elementwise. Choose a random element from the available elements. Exclude elements on top and left of the element to be set:
nx = 15;
ny = 10;
pool = 1:9; % Choose values 1:9, multiply by 2 finally
M = zeros(ny, nx);
for ix = 1:nx
for iy = 1:ny
% Exclude elements on the left and on the top from pool:
exclude = [M(gt0(iy - 1), ix), M(iy, gt0(ix - 1))];
choose = pool;
choose(exclude) = [];
% Nicer but slower in one line:
% choose = setdiff(pool, [M(gt0(iy - 1), ix), M(iy, gt0(ix - 1))]);
% Choose a random element from the remaining list:
M(iy, ix) = choose(randi(numel(choose)));
end
end
M = M * 2
ans = 10×15
6 16 14 8 14 16 14 18 14 6 8 16 18 10 18 18 10 18 4 6 4 18 10 6 4 12 6 8 14 6 2 4 14 18 16 6 16 8 4 10 18 12 14 8 16 4 6 12 8 2 10 6 18 6 14 8 6 18 16 12 8 12 4 2 18 16 10 14 2 10 2 10 6 2 14 10 14 18 14 2 4 16 4 10 6 12 6 12 14 6 8 10 12 2 8 6 12 18 14 18 6 18 8 4 18 14 18 8 6 2 8 14 2 8 6 14 16 18 12 6 16 14 18 12 18 4 2 12 10 18 6 12 16 10 12 6 8 16 6 8 18 12 8 4 8 16 6 18 6 8
function k = gt0(k)
% Reply [] as index, if it is <= 0
if k <= 0, k = []; end
end
I've experimented with cumsum(cumsum(randi([1, 9], 10, 15), 1), 2): There are no repetitions. Then limit the values by rem(). This was not successful. In one dimension it is working, but not in 2.
  6 comentarios
Francisco Boudagh
Francisco Boudagh el 26 de Nov. de 2021
@Image Analyst. Yes please, you can send me latin square code :-)
Image Analyst
Image Analyst el 26 de Nov. de 2021
Editada: Image Analyst el 26 de Nov. de 2021
Latin Squares are a very important concept in the "Design of Experiments" (DOX).
Actually there is Latin Square code in the File Exchange:

Iniciar sesión para comentar.

Más respuestas (2)

the cyclist
the cyclist el 26 de Nov. de 2021
Editada: the cyclist el 26 de Nov. de 2021
I believe this does what you want.
% Set the random number seed, for reproducibility
rng default
% The pool of random numbers to choose from
pool = 2:2:18;
% The size of the array
M = 10;
N = 15;
% Preallocate the output array
out = zeros(M,N);
% Fill the upper-left element from the pool
out(1,1) = randsample(pool,1);
% Fill the first column, never repeating the just-above value
for i1 = 2:M
out(i1,1) = randsample(setxor(pool,out(i1-1,1)),1);
end
% Fill the first row, never repeating the just-left value
for j1 = 2:N
out(1,j1) = randsample(setxor(pool,out(1,j1-1)),1);
end
% Fill the rest of the array, never repeating the just-above and just-left values
for ii = 2:M
for jj = 2:N
out(ii,jj) = randsample(setxor(pool,[out(ii-1,jj),out(ii,jj-1)]),1);
end
end
out
out = 10×15
16 12 16 12 14 12 14 6 2 14 18 8 16 4 10 4 14 4 14 2 18 10 16 10 18 10 4 14 16 18 14 4 12 6 14 16 14 6 2 10 18 10 2 6 8 6 8 4 14 8 4 6 12 4 2 4 16 4 8 10 18 4 6 18 10 16 8 6 8 6 10 18 10 6 8 4 16 4 2 18 10 4 16 2 14 12 8 16 12 6 18 12 18 10 8 12 16 12 16 6 18 12 4 10 16 14 4 6 8 10 18 8 4 12 14 4 8 10 2 14 8 18 10 4 18 10 12 14 6 2 18 2 8 4 2 16 8 16 18 12 2 10 18 12 16 4 18 10 18 10
I would caution you, though, that I have not thought carefully about the random properties of this array. (For example, does each element have equal probability for each value, etc., that might be important to you.) I think it's probably OK.
Also, if you do not have the Statistics and Machine Learning Toolbox, you will not have the randsample function, and therefore will need to replicate that function's behavior.
  3 comentarios
Jan
Jan el 26 de Nov. de 2021
@the cyclist: If we suggest equivalent algorithm, is it polite or vain, when I consider this as reason to vote for your answer? I cannot solve the emotional dilemma. Luckily this problem has no relation to Matlab and need not be discussed. +1. :-)
I've avoided randsample, because the OP might not have the Statitics Toolbox.

Iniciar sesión para comentar.


Image Analyst
Image Analyst el 25 de Nov. de 2021
Just construct a Latin square for n=9, then multiply it by 2

Community Treasure Hunt

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

Start Hunting!

Translated by