好奇这个问题是否可以更优雅地解决(也许使用递归?)

问题描述 投票:0回答:1

我是一名生物学研究生,在我的项目中遇到了一个我很难解决的问题。我使用迭代方法解决了这个问题(下面将详细描述),但很好奇是否有更简单或更优雅的解决方案。

我想生成一个数字序列。假设我们有向量

v = 1:12
。我想生成一个由向量
v = 1:12
组成的序列,其中有
n
重复。所得序列的长度为
v * n
。此外,对于这个序列的每个元素,我想添加一个布尔值(我将在下面解释更多)。

我希望这个序列满足几个条件:

  1. 在向量
    v
    的每次重复中,我希望元素
    1:12
    以随机顺序出现。 (这对我来说似乎很简单)
  2. 分配给序列中每个元素的布尔值必须在重复中保持平衡。也就是说,对于给定的第
    n
    次重复,我希望有
    6 true
    6 false
  3. 向量
    v
    中的每个值在整个序列中都应具有相同数量的
    true
    false

例如,如果

n=10
,我有一个长度为
120
的序列。在这个序列中,应该有
1
以及
5 true
5 false
2
5 true
5 false
等等。

我试图通过施加条件来解决这个问题。如果我们在生成初始重复时真的很不幸,通过

n/2
重复,我们可能会在
v
中得到一个永远不会得到
true
绘制的值。然后,我需要设置一个条件,即需要在剩余的重复等中绘制该值。您可以对仅绘制一次、两次等的值应用类似的逻辑..

解决这个问题最简单的方法是什么?我在 MATLAB 中有一段代码可以运行,但很想听到更多解决方案。这让我想起了一个数独问题,但老实说,我不得不承认我花了太多时间试图解决这个问题,所以我正在寻求帮助。谢谢!

编辑:我没有想到的另一个条件是向量

v
应该具有偶数大小,这样我就可以有偶数个
true
false
分配。因此
1:4
2
重复向量将如下所示:
1 3 2 4 2 3 1 4
1 1 0 0 1 0 0 1
。如果这可以扩展到像
2/3 true
1/3 false
..

这样的情况,我会很感兴趣
random pseudocode
1个回答
0
投票

如果我正确理解了您的要求,则可以通过将每个数值与由相等数量的二进制 true 和 false 组成的打乱集合配对来解决,然后将配对打乱

n
次并从当前迭代的打乱后构造输出值和在迭代索引处找到的相应二进制值。

在这种情况下,我认为代码比英文描述更清晰。既然你标记了伪代码,我就选择用 Ruby 来实现它,这非常接近伪代码。

首先,让我们创建配对:

N = 2

# Define a structure containing a value and associated binary values
PairedSet = Struct.new(:value, :binary_values)

# Now create an array with four of the structures. The value is set
# to the current iteration plus 1 (ruby arrays have 0-based indexing).
# The binary values are set to the desired number of trues and false,
# then shuffled.
collection = Array.new(4) do |i|
  PairedSet.new(i+1, [1, 1, 0, 0].shuffle )
end

# Pretty print the collection, followed by a blank line.
pp collection
puts

此时

collection
的示例输出如下所示:

[#<struct PairedSet value=1, binary_values=[0, 1, 0, 1]>,
 #<struct PairedSet value=2, binary_values=[1, 0, 1, 0]>,
 #<struct PairedSet value=3, binary_values=[1, 0, 0, 1]>,
 #<struct PairedSet value=4, binary_values=[0, 0, 1, 1]>]

现在我们创建空数组来收集输出,然后迭代

collection
所需的次数。当前迭代由
i
索引。对于每次迭代,我们都会对集合进行打乱,以便值和关联的二进制值将以随机顺序出现。我们将每对的
value
连接到值输出数组,并将当前迭代的关联布尔值连接到布尔输出数组。最后,我们打印两组输出。请注意,它们垂直对齐,我们可以轻松确认每个值都通过索引与所需的真/假数相关联。

values = []
bools = []
N.times do |i|
  collection.shuffle.each do |pair|
    values << pair.value
    bools << pair.binary_values[i]
  end
end

puts values.inspect
puts bools.inspect

产生示例结果,例如:

[1, 3, 4, 2, 4, 1, 2, 3]
[0, 1, 0, 1, 0, 1, 0, 0]

注意洗牌是随机的,因此如果您运行提供的代码,您应该期望不同的实际结果。

© www.soinside.com 2019 - 2024. All rights reserved.