打乱重复数字的向量,使数字在 MATLAB 中不重复
Shuffle a vector of repeated numbers so the numbers do not repeat in MATLAB
好的,所以我有一个脚本可以生成我的特定间隔的重复整数向量,但现在有一个特定的实例,我需要确保一旦它被打乱,数字就不会重复。因此,例如,我生成了一个重复 1-5、36 次的向量,打乱了顺序。如何保证洗牌后没有重号?为了使事情变得更加复杂,我需要生成两个这样的向量,它们在同一索引处永远不会具有相同的值。例如,假设 1:5 对于这些向量重复了两次,那么这就是我正在寻找的:
v1 v2
4 2
2 4
3 2
5 3
4 5
1 4
5 1
1 5
3 1
2 3
我现在通过以 1 个向量为例并将其偏移 1 来创建另一个满足要求的向量来实现这一点,但在我的情况下,这实际上行不通,因为我不能拥有它们像那样系统地依赖
所以我尝试了一种递归技术,让脚本在向量没有达到预期效果的情况下重新开始,正如预期的那样,结果并没有那么顺利。我达到了我的最大递归迭代次数并且我意识到这显然不是可行的方法。还有其他选择吗?
编辑:
所以我在下面的代码中找到了一种方法来满足我上面需要的一些条件:
a = nchoosek(1:5,2);
b = horzcat(a(:,2),a(:,1));
c = vertcat(a,b);
cols = repmat(c,9,1);
cols = cols(randperm(180),:);
我只需要找到一种随机排列 cols 的方法,该方法也将强制列中没有重复数字,例如 cols(i,1) ~= cols(i+1,1) 和 cols(i,2) ~= cols(i+1,2)
这可行,但对于大型数组来说可能不是很有效:
a = nchoosek(1:5, 2);
while (any(a(1: end - 1, 1) == a(2: end, 1)) ...
|| any(a(1: end - 1, 2) == a(2: end, 2)))
random_indices = randperm(size(a, 1));
a = a(random_indices, :);
end
a
如果你想要更快的东西,诀窍是在逻辑上将每一行插入满足你的条件的地方,而不是随机重新洗牌。例如:
n1 = 5;
n2 = 9;
a = nchoosek(1:n1, 2);
b = horzcat(a(:,2), a(:,1));
c = vertcat(a, b);
d = repmat(c, n2, 1);
d = d(randperm(n1 * n2), :);
% Perform an "insertion shuffle"
for k = 2: n1 * n2
% Grab row k from array d. Walk down the rows until a position is
% found where row k does not repeat with its upstairs or downstairs
% neighbors.
m = 1;
while (any(d(k,:) == d(m,:)) || any(d(k,:) == d(m+1,:)))
m = m + 1;
end
% Insert row k in the proper position.
if (m < k)
ind = [ 1: m k m+1: k-1 k+1: n1 * n2 ];
else
ind = [ 1: k-1 k+1: m k m+1: n1 * n2 ];
end
d = d(ind,:);
end
d
解决此问题的一种方法是将两个向量视为按如下方式创建:
对于数组 v1 和 v2 的每一行
- 随机排列数组
[1 2 3 4 5]
- 将当前行的v1和v2的值设置为shuffle的第一个和第二个值。两个值总是不同的。
代码:
s = [1 2 3 4 5];
Nrows = 36;
solution = zeros(Nrows,2);
for k=1:Nrows
% obtain indexes j for shuffling array s
[x,j] = sort(rand(1,5));
%row k takes the first two values of shuffled array s
solution(k,1:2) = s(j(1:2));
end
v1 = solution(:,1);
v2 = solution(:,2);
主要编辑:随机 => 随机数,
使用这种方法,不会浪费时间重新滚动重复数字,因为洗牌的第一个和第二个值 [1 2 3 4 5] 总是不同的。
如果您需要两个以上具有不同数字的数组,更改很简单。
好的,所以我有一个脚本可以生成我的特定间隔的重复整数向量,但现在有一个特定的实例,我需要确保一旦它被打乱,数字就不会重复。因此,例如,我生成了一个重复 1-5、36 次的向量,打乱了顺序。如何保证洗牌后没有重号?为了使事情变得更加复杂,我需要生成两个这样的向量,它们在同一索引处永远不会具有相同的值。例如,假设 1:5 对于这些向量重复了两次,那么这就是我正在寻找的:
v1 v2
4 2
2 4
3 2
5 3
4 5
1 4
5 1
1 5
3 1
2 3
我现在通过以 1 个向量为例并将其偏移 1 来创建另一个满足要求的向量来实现这一点,但在我的情况下,这实际上行不通,因为我不能拥有它们像那样系统地依赖
所以我尝试了一种递归技术,让脚本在向量没有达到预期效果的情况下重新开始,正如预期的那样,结果并没有那么顺利。我达到了我的最大递归迭代次数并且我意识到这显然不是可行的方法。还有其他选择吗?
编辑:
所以我在下面的代码中找到了一种方法来满足我上面需要的一些条件:
a = nchoosek(1:5,2);
b = horzcat(a(:,2),a(:,1));
c = vertcat(a,b);
cols = repmat(c,9,1);
cols = cols(randperm(180),:);
我只需要找到一种随机排列 cols 的方法,该方法也将强制列中没有重复数字,例如 cols(i,1) ~= cols(i+1,1) 和 cols(i,2) ~= cols(i+1,2)
这可行,但对于大型数组来说可能不是很有效:
a = nchoosek(1:5, 2);
while (any(a(1: end - 1, 1) == a(2: end, 1)) ...
|| any(a(1: end - 1, 2) == a(2: end, 2)))
random_indices = randperm(size(a, 1));
a = a(random_indices, :);
end
a
如果你想要更快的东西,诀窍是在逻辑上将每一行插入满足你的条件的地方,而不是随机重新洗牌。例如:
n1 = 5;
n2 = 9;
a = nchoosek(1:n1, 2);
b = horzcat(a(:,2), a(:,1));
c = vertcat(a, b);
d = repmat(c, n2, 1);
d = d(randperm(n1 * n2), :);
% Perform an "insertion shuffle"
for k = 2: n1 * n2
% Grab row k from array d. Walk down the rows until a position is
% found where row k does not repeat with its upstairs or downstairs
% neighbors.
m = 1;
while (any(d(k,:) == d(m,:)) || any(d(k,:) == d(m+1,:)))
m = m + 1;
end
% Insert row k in the proper position.
if (m < k)
ind = [ 1: m k m+1: k-1 k+1: n1 * n2 ];
else
ind = [ 1: k-1 k+1: m k m+1: n1 * n2 ];
end
d = d(ind,:);
end
d
解决此问题的一种方法是将两个向量视为按如下方式创建:
对于数组 v1 和 v2 的每一行
- 随机排列数组
[1 2 3 4 5]
- 将当前行的v1和v2的值设置为shuffle的第一个和第二个值。两个值总是不同的。
代码:
s = [1 2 3 4 5];
Nrows = 36;
solution = zeros(Nrows,2);
for k=1:Nrows
% obtain indexes j for shuffling array s
[x,j] = sort(rand(1,5));
%row k takes the first two values of shuffled array s
solution(k,1:2) = s(j(1:2));
end
v1 = solution(:,1);
v2 = solution(:,2);
主要编辑:随机 => 随机数,
使用这种方法,不会浪费时间重新滚动重复数字,因为洗牌的第一个和第二个值 [1 2 3 4 5] 总是不同的。 如果您需要两个以上具有不同数字的数组,更改很简单。