How do I make a random exchange, but impose a limit on how far this number can move from its original position?

A set of 20 numbers is stored inside the vector d , for example:

 d = [ 5 6 7 8 9 ....] 

I use

 i = randperm(length(d)); d = d(i); 

to randomly shuffle the numbers inside the matrix.

However, I need to find a way to limit shuffling so that the number does not move more than "5" from the starting position?

The value, if initially d(2) = 6 final position 6 should move only by d(1) to d(2+5) .

Note d(1) , because the numbers cannot go into a negative position.

Any help on this would be appreciated! Also, if there is a more efficient way with shuffling, please kindly inform me!

+6
source share
2 answers

My solution would be to create a random permutation and swap bad indices if no index violates the distance rule.

 d=data delta=5; i= randperm(length(d)); v=badPosition(i); while(v~=0) %lower bound for position a=max(1,i(v)-5); %upper bound for position A=min(numel(i),i(v)+5); spos=randi([a,A]); h=i(v); i(v)=i(spos); i(spos)=h; v=badPosition(i); end d=d(i) 

 function pos=badPosition(indices) delta=5; allPos=(find(indices>(1:numel(indices))+delta|indices<(1:numel(indices))-delta)); if numel(allPos)>0 pos=allPos(randi(numel(allPos))); else pos=0; end end 

badPosition is a function that returns 0 if all indices are in order or one index that violates the distance rule. If there are multiple violations, a random index is selected.

+2
source

This solution will scale better:

 n=2000; I = 1:n; k = 5; for ii = 1+k:nk t = I(ii); s = t + randi(2*k,1)-k; if abs(I(s) - ii) <= k I(ii) = I(s); I(s) = t; end end 

Then do data(I) . This incorrectly takes into account edge cases, but I think you can quite easily customize for this.

I tried it for n=100000 and it worked in less than a second.

However, the movement is not evenly distributed.

0
source

All Articles