отказ от ответственности: это решение не идеально.
Хорошо, поэтому мой итеративный подход заключается в создании перестановочного вектора из всех возможных испытаний и последующем добавлении каждого из них к другому вектору, если он не нарушает более 3 последовательных условий одного типа .
Сначала я настрою некоторые константы
N_CONDITIONS = 5;
TRIALS_PER_CONDITION = [10 10 10 7 9];
N_DUPS_ALLOWED = 3;
N_TOTAL = sum(TRIALS_PER_CONDITION);
Затем я создаю случайную перестановку всех испытаний:
randomInds = randperm(N_TOTAL);
% make vector containing all the replicates
conditionTrials = repelem(1:N_CONDITIONS, TRIALS_PER_CONDITION);
% permute the conditions
conditionTrials = conditionTrials(randomInds);
Затем я готовлюсь зациклить элемент вектора conditionTrials
элементом
% 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) = [];
Затем я устанавливаю переменные / счетчики цикла и выполняю цикл:
% 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
Цикл по существу утверждает: %, хотя в векторе randomizedTrials присутствует хотя бы 1 ноль, проверьте, нарушает ли следующее значение N_DUPS_ALLOWED
. Если нарушений нет, извлеките его из вектора conditionTrials
и добавьте к вектору randomizedTrials
. В противном случае повторно включите испытания и повторите попытку.
Я также написал в проверке, чтобы убедиться, что мы не зацикливаемся вечно ... как может быть, если мы подойдем к концу вектора и получим много повторов.