How do you randomize numbers but not have two consecutive numbers be the same?

3 views (last 30 days)
I have 25 different tones (5 frequencies, 5 amplitudes in combination) and I need to play them in a randomized order, but I do not want any tones with the same frequency or amplitude to be next to each other.
my script plays the tones according to my currently randomized order for example:
column 1 corresponding to frequency (1-5 for the 5 different frequencies) and column 2 corresponding to amplitude (1-5 for the different amplitudes)
1 4
2 4
4 2
5 5
4 4
4 5
3 5
5 2
1 3
4 3
3 4
4 1
2 3
5 1
1 1
3 2
1 2
1 5
5 4
2 2
2 5
3 3
5 3
3 1
2 1
How can I edit my script so that no sounds of the same frequency or amplitude are played consecutively?
  3 Comments
bym
bym on 25 Jan 2011
If you want them in a random order,couldn't that include the possibility that the same frequency and amplitude is played consecutively?
Lisa
Lisa on 25 Jan 2011
Hi, I'm sorry the formatting of the numbers did not come out correctly. but yes, there should be 2 columns with 25 rows, each with a coordinate of (freq, amp). I have 25 different tones, 5 freq x 5 amplitudes, and I would like them to play in a randomized order each time, but not allowing tones of either the same freq or amplitude to be consecutive. so, im looking for a way to 'pseudorandomize' them

Sign in to comment.

Answers (8)

Matt Fig
Matt Fig on 25 Jan 2011
Use the RANDPERM function. Depending on what you want to do, pick one of these:
>> A = [1 2;3 4;5 6;7 8;9 10] % Sample Data
A =
1 2
3 4
5 6
7 8
9 10
>> A(randperm(5),:) % Keep rows the same, but different order
ans =
7 8
9 10
3 4
1 2
5 6
>> [A(randperm(5),1), A(randperm(5),2)] % Mix rows and cols separately
ans =
3 8
7 6
5 10
1 2
9 4

Paulo Silva
Paulo Silva on 25 Jan 2011
function d=selpair(b,s)
%The input b is a column matrix with even values
%The input s is the number of pairs of values
%The output d is the a values but without being repeated
%by Paulo Silva
e=0;
for c=1:s
d(c,:)=b(1+e,:);
b(1+e,:)=[];e=0;
while(isempty(b) | d(c,:)==b(1+e,:))
e=e+1;
if ((e>=(s-1)) | (numel(b(:,1))<2))
return
end
end
end
To test the function use your data or this one
clc
clear
Pairs=25;
a=zeros(Pairs,2);
a(:,1)=round(0.5+abs(5*rand(Pairs,1)));
a(:,2)=round(0.5+abs(5*rand(Pairs,1)));
SortedData=selpair(a,Pairs);
  6 Comments
Lisa
Lisa on 25 Jan 2011
yes, i was able to get the function to work. thank you
however, the sorted data i got was:
4 4
3 4
4 2
1 5
5 5
3 2
5 1
2 2
5 1
4 4
3 5
5 4
5 5
4 4
4 3
3 5
5 3
4 4
1 2
1 4
2 4
5 3
2 4
1 2
4 1
is there a way for me to make sure no 2 consecutive tones have the same frequency OR amplitude? For example, in this data, the first 2 tones have the same amplitude. (freq = 1st column, amp=2nd column)
thank you for your help! it is much appreciated
Paulo Silva
Paulo Silva on 25 Jan 2011
I made the function to detect same freq and tone, it was my mistake, I will change the code to do what you want

Sign in to comment.


Paulo Silva
Paulo Silva on 25 Jan 2011
Here's a better version, I included Matt Fig idea of the permutation, now my function can also randomize the rows of data and apply restrictions.
function d=selpair(b,at)
%The input at is the number of attempts that the function makes
%After the first attempt fails and if at>1 it will do a permutation of
%the rows of the data and try again, it will do permutations until all the
%data restrictions are satisfied or number attemps = at
%Made by Paulo Silva 25-01-2010
s=numel(b(:,1));
for atn=1:at
b=b(randperm(s),:); %randomize the rows
[d code]=selpairfind(b,s);
if (code==1)
break
else
%move the randperm line to this line if you don't want the data
%to be randomized at the first attempt
end
end
function [d code]=selpairfind(b,s)
%The input b is a (s,2) matrix
%The input s is the number of tones
%The output d is the matrix b but without consecutive rows with
%the same freq or amp, other detections are included
%just uncomment the line with the while you want and comment the others
%The returned value might not have the same size as the input
%(less lines), this is because the function can't satisfy the condition,
%it happens in the end of the data.
e=0;
for c=1:s
d(c,:)=b(1+e,:);
b(1+e,:)=[];e=0;
%detect same freq
%while((isempty(b)) | (d(c,1)==b(1+e,1)))
%detect same amp
%while((isempty(b)) | (d(c,2)==b(1+e,2)))
%detect same freq and amp
%while((isempty(b)) | (d(c,:)==b(1+e,:)))
%detect same freq or amp
while((isempty(b)) | ((d(c,1)==b(1+e,1))|(d(c,2)==b(1+e,2))))
e=e+1;
if ((e>=(numel(b(:,1))-1)) | (numel(b(:,1))<2))
%Sometimes the function cannot satisfy the condition very near
%the end of the data, some lines are ignore and the output size
%is smaller than the input, if you wish the size to be always the
%same just uncomment the next line (=no condition for that data)
%d=[d;b];
if (isempty(b))
code=1;
else
code=0;
end
return
end
end
end
end
end
Code to test and compare the data
clc
clear
clf
Pairs=25;
at=10; %number of attempts
a=zeros(Pairs,2);
a(:,1)=round(0.5+abs(5*rand(Pairs,1)));
a(:,2)=round(0.5+abs(5*rand(Pairs,1)));
SortedData=selpair(a,Pairs,at);
subplot(211)
plot(a)
xlabel('Original data, the horizontal lines are repeated values')
legend('Freq','Amp')
subplot(212)
plot(SortedData)
xlabel('Filtered data')
legend('Freq','Amp')

Bruno Luong
Bruno Luong on 25 Jan 2011
Generate 100 pairs, no two consecutive pair has the same frequency OR the same amplitude:
% Data
f = (1:5)'
a = (1:5)'
Npairs = 100
% number of elements of f and a
nf = numel(f); % 5
na = numel(a); % 5
% Engine
indf = ceil((nf-1)*rand(Npairs,1)); % 0 excluded
indf = mod(cumsum(indf),nf)+1; % wrap around (0:nf)
inda = ceil((na-1)*rand(Npairs,1));
inda = mod(cumsum(inda),na)+1;
pairs = [f(indf) a(inda)] % two columns F and A
% Bruno
  6 Comments
Matt Fig
Matt Fig on 25 Jan 2011
It should be pointed out, for clarity, that if the original row order is to be preserved, then only one of indf or inda is needed.

Sign in to comment.


Paulo Silva
Paulo Silva on 25 Jan 2011
function d=selpair(b,s)
%The input a is a column matrix with even values
%The input s is the number of pairs of values
%The output f is the a values but without consecutive rows with
%the same freq or amp
e=0;
for c=1:s
d(c,:)=b(1+e,:);
b(1+e,:)=[];e=0;
while((isempty(b)) | ((d(c,1)==b(1+e,1))|(d(c,2)==b(1+e,2))))
e=e+1;
if ((e>=(s-1)) | (numel(b(:,1))<2))
return
end
end
end
  3 Comments
Walter Roberson
Walter Roberson on 25 Jan 2011
Paulo, you could have just changed d(c,:)==b(1+e,:) to any(d(c,:)==b(1+e,:))

Sign in to comment.


Paulo Silva
Paulo Silva on 25 Jan 2011
function d=selpair(b,s)
%The input b is a (s,2) matrix
%The input s is the number of tones
%The output d is the matrix b but without consecutive rows with
%the same freq or amp, other detections are included
%just uncomment the line with the while you want and comment the others
%The returned value might not have the same size as the input
%(less lines), this is because the function can't satisfy the condition,
%it happens in the end of the data.
e=0;
for c=1:s
d(c,:)=b(1+e,:);
b(1+e,:)=[];e=0;
%detect same freq
%while((isempty(b)) | (d(c,1)==b(1+e,1)))
%detect same amp
%while((isempty(b)) | (d(c,2)==b(1+e,2)))
%detect same freq and amp
%while((isempty(b)) | (d(c,:)==b(1+e,:)))
%detect same freq or amp
while((isempty(b)) | ((d(c,1)==b(1+e,1))|(d(c,2)==b(1+e,2))))
e=e+1;
if ((e>=(numel(b(:,1))-1)) | (numel(b(:,1))<2)) % * error fixed *
%Sometimes the function cannot satisfy the condition very near
%the end of the data, some lines are ignore and the output size
%is smaller than the input, if you wish the size to be always the
%same just uncomment the next line (=no condition for that data)
%d=[d;b];
return
end
end
end
Code to test and compare the data
clc
clear
clf
Pairs=25;
a=zeros(Pairs,2);
a(:,1)=round(0.5+abs(5*rand(Pairs,1)));
a(:,2)=round(0.5+abs(5*rand(Pairs,1)));
SortedData=selpair(a,Pairs);
subplot(211)
plot(a)
xlabel('Original data, the horizontal lines are repeated values')
legend('Freq','Amp')
subplot(212)
plot(SortedData)
xlabel('Filtered data')
legend('Freq','Amp')

Paulo Silva
Paulo Silva on 25 Jan 2011
Another implementation, please test it and report all possible errors
function d=selpair(b,at,Tdet,r1)
%The input at is the number of attempts that the function makes
%Tdet is the type of detection
%Tdet=1 detects same freq
%Tdet=2 detects same amp
%Tdet=3 detects same freq and amp
%Tdet=4 detects same freq or amp
%The input r1 enables the permutation of the data also in first attempt
%r1=1 yes do permutation at first
%r1~=1 no, try first without permutation
%it will do permutations until all the data restrictions are
%satisfied or number attemps = at
%Made by Paulo Silva 25-01-2010
s=numel(b(:,1));
for atn=1:at
[d code bres]=selpairfind(b,s,Tdet);
if (code==1)
disp('Success, data returned with all conditions satisfied')
break
else
if ((atn~=1) | ((r1==1) & (atn==1)))
b=b(randperm(s),:); %randomize the rows
end
end
end
if (code==0)
disp('Failed to satisfy all conditions, try again with more attempts')
message=sprintf('The last %d lines dont satisfy the conditions',numel(bres(:,1)));
disp(message)
userchoice=input('Do you still want to include those lines? y/n ','s');
if (strcmp(userchoice,'y') | strcmp(userchoice,'yes'))
disp('Success, data returned with all conditions satisfied exept last lines')
d=[d;bres];
end
end
function [d code b]=selpairfind(b,s,Tdet)
%The input b is a (s,2) matrix
%The input s is the number of tones
%Tdet is the type of detection
%Tdet=1 detects same freq
%Tdet=2 detects same amp
%Tdet=3 detects same freq and amp
%Tdet=4 detects same freq or amp
%The output d is the matrix b but without consecutive rows with
%the same freq or amp, other detections are included
%just uncomment the line with the while you want and comment the others
%The returned value might not have the same size as the input
%(less lines), this is because the function can't satisfy the condition,
%it happens in the end of the data.
e=0;
for c=1:s
d(c,:)=b(1+e,:);
b(1+e,:)=[];e=0;
if ((isempty(b)))
condwhile=1;
else
if (Tdet==1)
%detect same freq
condwhile=((d(c,1)==b(1+e,1)));
end
if (Tdet==2)
%detect same amp
condwhile=((d(c,2)==b(1+e,2)));
end
if (Tdet==3)
%detect same freq and amp
condwhile=((d(c,:)==b(1+e,:)));
end
if (Tdet==4)
%detect same freq or amp
condwhile=(((d(c,1)==b(1+e,1))|(d(c,2)==b(1+e,2))));
end
end
while(condwhile)
e=e+1;
if ((e>=(numel(b(:,1))-1)) | (numel(b(:,1))<2))
if (isempty(b))
code=1;
else
code=0;
end
return
end
end
end
end
end

J Richards
J Richards on 18 Apr 2012
Hi there,
Does anyone know of a way to stop elements from being repeated more than three times in a row? I have a 3 x 920 matrix consisting of the numbers 1 to 4, and wish to ensure that no number occurs more than 3 times consecutively in any column.
Thanks,
James

Categories

Find more on Mathematics in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!