【问题标题】:Shuffle an array of unequally repeating entries, so they do not repeat [closed]随机播放一组不相等重复的条目,因此它们不会重复[关闭]
【发布时间】:2019-08-15 12:24:39
【问题描述】:

我正在 Matlab Psychtoolbox 中编写一个实验,我的条件存储在这样的数组中

Cond = ["VM" "VM" "VN" "VS" "AM" "AM" "AN" "AS" "CM" "CM" "CN" "CS"...
"VM" "VM" "VN" "VS" "AM" "AM" "AN" "AS" "CM" "CM" "CN" "CS"];

我现在想以没有重复条件的方式对数组进行洗牌。

有很多关于这个问题的处理方法,例如this one,但它们总是同样频繁地出现每种情况。

有些人提出了一种蛮力方法,经常洗牌,直到达到这个标准。但由于我有这种条件数组的树,并且每次实验运行都必须将它们洗牌几次,我认为这不是一个好的解决方案。

希望有人能帮忙

【问题讨论】:

  • 我不确定您是否可以“有条件地随机播放”。如果您想要随机洗牌,请这样做直到它符合您的标准。否则,请找到一种算法,使用特定约束对数据进行排序(而不是打乱)。但是如果你想要随机性,那么你需要使用蛮力方法。 (我认为)
  • 此外,您不必在每次实验时都强制执行,只需生成满足您的“打乱”条件的所有可能组合的列表并随机选择其中一个排列。
  • 如何随机打乱数组,然后遍历它并获取与其前身相等的每个元素并将其移动到末尾。然后,最后你可能有一些不满足你的条件的元素。获取这些元素并通过再次遍历数组并找到与该元素不同的两个连续元素并将其插入其中来为每个元素找到一个位置。

标签: arrays matlab shuffle psychtoolbox


【解决方案1】:

我设计了一种算法,可以满足您的要求。给定一个序列,它将随机重新排序,使得没有值重复。但是,它似乎确实倾向于创建重复的子序列(例如..."A" "B" "C" "A" "B" "C"...)。我把它包装在一个函数reorder_no_reps

function seq = reorder_no_reps(seq)

  % Find unique values and counts:
  N = numel(seq);
  [vals, ~, index] = unique(seq(:), 'stable');
  counts = accumarray(index, 1);
  [maxCount, maxIndex] = max(counts);

  % Check the maximum number of occurrences:
  if (2*maxCount-1 > N)
    error('Can''t produce sequence without repeats!');
  end

  % Fill cell array column-wise with permuted and replicated set of values:
  C = cell(maxCount, ceil(N/maxCount));
  if (3*maxCount-1 > N)
    permIndex = [maxIndex(1) ...
                 setdiff(randperm(numel(vals)), maxIndex(1), 'stable')];
  else
    permIndex = randperm(numel(vals));
  end
  C(1:N) = num2cell(repelem(vals(permIndex), counts(permIndex)));

  % Transpose cell array and extract non-empty entries:
  C = C.';
  seq = reshape([C{~cellfun('isempty', C)}], size(seq));

end

算法步骤说明:

  • 查找输入序列中的唯一值 (vals) 以及它们各自出现的次数 (counts)。
  • 查找单个值 (maxCounts) 的最大出现次数,并检查它是否太大而无法生成不重复的序列。
  • 随机排列顺序应用于唯一值及其计数。如果最大出现次数超过给定阈值,则相应的值索引将移至随机顺序的开头(原因将在下一个项目符号中说明)。
  • 然后每个唯一值按其在序列中出现的次数就地复制。用这些复制的值按列顺序填充一个单元格数组,最后可能会留下一些单元格为空。由于元胞数组的行数等于某个值的最大出现次数,因此生成的元胞数组的任何一行都不会有一个值在其中出现多次。此外,每行中的最后一个值应不同于后续行中的第一个值(在某些情况下,通过首先填充最常出现的值来确保)。
  • 转置单元格数组,然后按列顺序拉出所有非空单元格值,并将它们重新整形为与输入序列相同的大小。这与从非转置元胞数组中逐行提取值相同,这应该会为您提供一个没有重复值的序列。

【讨论】:

  • 嘿@gnovice,你的算法很好用。你是对的,它创建了重复的子序列。对我来说这很好,但对于重复次数较多的人来说,这可能会有问题。
猜你喜欢
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-16
  • 1970-01-01
  • 2011-11-10
  • 2012-10-23
  • 1970-01-01
相关资源
最近更新 更多