Q:

How to pseudo-randomize trials without repeating same condition more than three times

I know there are lots of pseudo-randomization skills but this one, I couldn't search it so I put it on here.
I am using MATLAB 2018a. I've been trying to set up a behavior experiment which has 10 conditions. Each condition has 50 trials. This results in 500 trials total. 
I would like to pseudo-randomize the sequence of trials such that no same conditions appear more than three times consecutively. 
I thought it would be not so difficult since I have many conditions but some of the methods I found by googling had minor problems. One of the methods I used was by extracting indexes using 'unique(find(diff(seq)==0))', re-randomize it and replace it with the original redundant sequence. (Link) But this method had a problem that it would randomly change the total number of a condition. If you wanted 40 trials for each condition, it would result in 39 for some conditions while 41 for others..
My question would be how to improve this method to have constraints of having no one condition repeated three times, while solving the problem mentioned above.
Or would there be any better ways?

A:

disclaimer: this solution is not perfect.
Ok, so my iterative approach is to create a permuted vector of all possible trials and then append each one to another vector if it doesn't violate the more than 3 consecutive conditions of the same type.
First, I'll set up some constants

N_CONDITIONS = 5;
TRIALS_PER_CONDITION = [10 10 10 7 9];
N_DUPS_ALLOWED = 3;

N_TOTAL = sum(TRIALS_PER_CONDITION);

Then I create a random permutation of all the trials:
randomInds = randperm(N_TOTAL);
% make vector containing all the replicates
conditionTrials = repelem(1:N_CONDITIONS, TRIALS_PER_CONDITION);

% permute the conditions
conditionTrials = conditionTrials(randomInds);

Then I prepare to loop over the conditionTrials vector element by element
% initialize the random trials vector
randomizedTrials = zeros(N_TOTAL, 1);

% pre assign the first allowable possible duplications
randomizedTrials(1:N_DUPS_ALLOWED) = conditionTrials(1:N_DUPS_ALLOWED);
% drop the used values
conditionTrials(1:N_DUPS_ALLOWED) = [];

Next, I setup the loop variables/counters and perform the loop:
% initialize counter
i = N_DUPS_ALLOWED + 1;
iterCounter = 1;
maxIter = 1000; % set me pretty low, but high enough for extra perms
while any(~randomizedTrials)
  iterCounter = iterCounter + 1;
  if iterCounter > maxIter 
    fprintf(2, '\nMaximum interations exceeded.\n');
    break
  end
  % get the value we want to test
  currentTrial = conditionTrials(1);
  % get the previes n_dups_allowed values
  previousConditions = randomizedTrials( i - (N_DUPS_ALLOWED:-1:1) );
  % check if they're the same
  if sum(previousConditions == currentTrial) == N_DUPS_ALLOWED
    % reject this value because last 3 values == currentValue
    % accepting would lead to > 3 consecutive trials
    % create a new shuffle
    newPermInds = randperm(length(conditionTrials));
    conditionTrials = conditionTrials(newPermInds);
    continue
  end
  % accept the random number, insert it in the trails vector
  randomizedTrials(i) = currentTrial;
  % now drop the value
  conditionTrials(1) = [];
  i = i+1;
end

The loop essentially states: %while at least 1 zero present in the randomizedTrials vector, check if the next value violates N_DUPS_ALLOWED. If no violation, pop it from the conditionTrials vector and append it to the randomizedTrials vector. Otherwise, re-permute the trials and try again.
I also wrote in a check to make sure we don't loop forever... as might be the case if we come toward the end of the vector and we get many replicates.

