2

I am trying to generate random numbers between 1 and 6 using Matlab's randperm and calling randperm = 6.

Each time this gives me a different array let's say for example:

x = randperm(6)
x = [3 2 4 1 5 6]

I was wondering if it was possible to create pairs of random numbers such that you end up with x like:

x = [3 4 1 2 5 6]

I need the vector to be arranged such that 1 and 2 are always next to each other, 3 and 4 next to each other and 5 and 6 next to each other. As I'm doing something in Psychtoolbox and this order is important.

Is it possible to have "blocks" of random order? I can't figure out how to do it.

Thanks

Maheen Siddiqui
  • 539
  • 8
  • 19
  • is the order of the pair important? e.g if there is a block of three numbers to be selected. Should it be, for example, strictly `1,2,3`? or all of the combinations are also possible which are `1,3,2` , `2,1,3`, `2,3,1`, `3,1,2` , `3,2,1` ? – Sardar Usama Aug 20 '17 at 21:49
  • Not strictly important but it would be good to know how to do it in case I wanted to implement that later on... – Maheen Siddiqui Aug 20 '17 at 21:52
  • Added how to have random order within each block alongwith how to have the numbers in ascending order in my answer – Sardar Usama Aug 20 '17 at 23:30

2 Answers2

4
x=1:block:t ;    %Numbers
req = bsxfun(@plus, x(randperm(t/block)),(0:block-1).');  %generating random blocks of #
%or req=x(randperm(t/block))+(0:block-1).' ; if you have MATLAB R2016b or later
req=req(:);      %reshape

where,
t = total numbers
block = numbers in one block

%Sample run with t=12 and block=3
>> req.'

ans =

    10    11    12     4     5     6     1     2     3     7     8     9

Edit:
If you also want the numbers within each block in random order, add the following 3 lines before the last line of above code:

[~, idx] = sort(rand(block,t/block));              %generating indices for shuffling
idx=bsxfun(@plus,idx,0:block:(t/block-1)*block);   %shuffled linear indices
req=req(idx);                                      %shuffled matrix

%Sample run with t=12 and block=3
req.'

ans =

     9     8     7     2     3     1    12    10    11     5     6     4
Sardar Usama
  • 19,536
  • 9
  • 36
  • 58
  • This looks like a more general solution, but would the order within each block be the same here? – Steve Aug 20 '17 at 22:11
  • 2
    @Steve The numbers within each block will always be increasing, because of the `(0:block-1).'` part – Luis Mendo Aug 20 '17 at 22:13
  • Thanks, it's a good solution as well. Just want to add for any future readers that I'm doing this multiple times in a loop so it's good to add "rand('state',sum(100.*clock));" at the beginning of the script otherwise eventually everything gets muddled up. – Maheen Siddiqui Aug 20 '17 at 22:28
  • Just a quick question... Is there a way for me to enforce that there should be equal no. of 'blocks' for example I re-generate the random sequence every time in my loop, can I make a condition so that I have 10 of each "block"? – Maheen Siddiqui Aug 20 '17 at 22:35
  • @Maheen do you want to have ten numbers in a block? then initialise `block=10` before the loop – Sardar Usama Aug 20 '17 at 22:38
  • 1
    @Maheen btw `rand('state',sum(100.*clock));` is discouraged by Mathworks. The recommended way is `rng('shuffle')`. [See doc](https://www.mathworks.com/help/matlab/math/updating-your-random-number-generator-syntax.html#bsu1ysw). – Sardar Usama Aug 20 '17 at 22:49
  • 1
    @Steve also added how to have different order within each block – Sardar Usama Aug 20 '17 at 23:26
  • @SardarUsama So I have changed my code and now I have to 5 conditions to permutate... i.e. my t=5 and I need the order such that 4 and 5 need to be together, the others don't matter... so for e.g. [3 1 2 4 5] or [2 3 1 4 5] etc. How do I do this using this code? Because randperm is only allowed for integers... Thanks!! – Maheen Siddiqui Aug 23 '17 at 22:40
  • @MaheenSiddiqui A new question *should* be asked as [a new question](https://stackoverflow.com/questions/ask) – Sardar Usama Aug 23 '17 at 22:46
  • @SardarUsama Asked as a new question now here: https://stackoverflow.com/questions/45850457/ordered-random-numbers-in-matlab – Maheen Siddiqui Aug 23 '17 at 22:51
3

I can see a simple 3 step process to get your desired output:

  1. Produce 2*randperm(3)
  2. Double up the values
  3. Add randperm(2)-2 (randomly ordered pair of (-1,0)) to each pair.

In code:

x = randperm(3)
y = 2*x([1 1 2 2 3 3])
z = y + ([randperm(2),randperm(2),randperm(2)]-2)

with result

x = 3 1 2
y = 6 6 2 2 4 4
z = 6 5 2 1 3 4
Steve
  • 1,579
  • 10
  • 23
  • Ahh, thanks! Just a quick question, would it be easy to rearrange so that I had them in increasing order, like 1 2 and 3 4 rather than 4 3? – Maheen Siddiqui Aug 20 '17 at 21:49
  • @MaheenSiddiqui if you want to always have the smaller number of the pair before the larger, then instead of adding `[randperm(2),randperm(2),randperm(2)]-2` to `y`, you'd add `repmat([-1,0],1,3)` (which is `[-1 0 -1 0 -1 0]`) to it – Steve Aug 20 '17 at 21:52