Tricky randomization issue - help needed!
显示 更早的评论
Dear Matlab folks,
I am struggling with the following issue:
I created 80 parings of numbers. These pairings should stay the same but the order of the pairings should be randomized.
So, I have a variable containing these pairings: sequence = [pairing_1 pairing_2 pairing_3 and so forth].
How can I randomize the order of these pairings? For example, it would look like this then: randomized_sequence = [pairing_2 pairing_3 pairing_1 .....]
And now for the tricky part:
The numbers of the pairings reach from 1 to 40. Every number from 1 to 40 is combined with one random even number between 1 and 40 and one random uneven number between 1 and 40. For 1, I could have the pairings 1 & 18 and 1 & 9 for example. But 1 must not be paired with 1! No number can be matched with itself. Furthermore, 1 must not be paired with 2 and 2 must not be paired with 1, the sequence doesn't matter. 3 must not be paired with 4, 5 must not be paired with 6 and so forth until 39 must not be paired with 40 and every time, the sequence doesn't matter. So, 39 and 40 is not possible as well as 40 and 39.
The numbers that must not be paired are:
1 2 | 3 4 | 5 6 | 7 8 | 9 10 | 11 12 | 13 14 | 15 16 | 17 18 | 19 20 | 21 22 | 23 24 | 25 26 | 27 28 | 29 30 | 31 32 | 33 34 | 35 36 | 37 38 | 39 40
So 2 and 3 can be paired, for example!
Now the problem is, if I have these 2 pairings 14 16 and 16 9 and after the shuffling of the pairings 14 16 lands before 16 9 then I have a 16 16 pairing as well which must not happen. Such unwanted pairings can happen a lot through the shuffling. For example, the 14 of 14 16 must not be preceeded by 14 or 13 and the 16 of 14 16 must not be followed by 16 or 15.
I was thinking about maybe coding something like: "If 1 is followed/preceded by 1 or 2 then shuffle again. If 2 is followed/preceded by 1 or 2 then shuffle again. If 3 is followed/preceded by 3 or 4 then shuffle again...." and so forth until "If 40 is followed/preceded by 40 or 39 then shuffle again."
What do you think, is there a way to do it like that? Or even a way easier solution, I did not think about?
I very much appreciate any help, this is bothering me since quite some time now.
Thanks in advance,
Rupert
7 个评论
It may take a long time to generate valid shiuffle if you need to exclude many of them.
How did you store the pairs? I hope you used an array instead of numbered variables.
Can you give a small example of input and valid output? You can make the example smaller (e.g. 6 instead of 40).
Rupert Steinmeier
2020-8-25
编辑:Rik
2020-8-25
Rik
2020-8-25
OK, let's first create an array with all pairs:
N=6;
all_ids=(1:N)';
odd=all_ids(1:2:end);
even=all_ids(2:2:end);
pair_with_even=even(randi(end,N,1));
pair_with_odd=odd(randi(end,N,1));
list_of_pairs=[all_ids pair_with_odd;all_ids pair_with_even];
list_of_pairs([1:2:end 2:2:end],:)=list_of_pairs;
Now you want to shuffle this. What exactly do you mean by preceding? Should the list be made linear, like you wrote in text?
Also note that it is generally a bad idea to use variables with numbers in them if you plan to do something with these numbers. Try to use arrays (i.e. matrices) instead of a long list of variables. And if you don't know the difference (after seeing my code): I would urge you to do the Matlab OnRamp tutorial. It is free and will teach you the Matlab basics.
(also: avoid the length function; you should use numel or size instead, because length can cause unexpected behavior if your input is not a vector)
Rupert Steinmeier
2020-8-26
Rik
2020-8-26
So by preceding you mean preceding, well, that cleared up your definition.
Let's linearize the array I generated:
reshape(list_of_pairs.',1,[])
%returns this list if rng(1) is put at the start of the code:
%1 1 1 4 2 3 2 6 3 3 3 2 4 3 4 2 5 3 5 2 6 5 6 2
Does it matter your horizontal bars are gone?
Can you try to write a function that will check if a sequence is valid? At least in words?
Rupert Steinmeier
2020-8-26
Rik
2020-8-26
It does take a while: 20370 tries if you shuffle the list, 884 tries if you don't.
采纳的回答
更多回答(1 个)
Mohammad Sami
2020-8-25
编辑:Rik
2020-8-25
One option can be to generate a sequence longer then you need and then eliminate values until the sequence is valid. Thereafter you can take desired length of sequence. If it's shorter generate again and concatenate it.
DesiredLength = 200;
N = 2 * DesiredLength;
Seq = randi([1 40],N,1);
while(any(abs(diff(Seq))<=1))
I = [false;abs(diff(Seq)) <= 1];
Seq(I) = [];
if(length(Seq)<DesiredLength)
Seq = [Seq;randi([1 40],N,1)];
end
end
Final = Seq(1:DesiredLength);
5 个评论
Rik
2020-8-25
I assume you were on mobile, so I took the liberty of editing your code.
Mohammad Sami
2020-8-26
Thanks Rik :)
Rupert Steinmeier
2020-8-26
Mohammad Sami
2020-8-26
Based on your description I assumed that the sequence is valid if the absolute difference between two consecutive number is > 1. So the code is essentially checking if the sequence is valid in the while loop. If there is any value where the absolute difference is less then or equal to 1 it is removed. The if statement just checks if the sequence is longer then the length you need after removing invalid values. In that case it generates and append more data. The while loop will terminate once there is no invalid pairing left.
Rupert Steinmeier
2020-8-26
类别
在 帮助中心 和 File Exchange 中查找有关 Entering Commands 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!