我有一个大小为n的数组,并希望将其分解为m个大小至少为3的块。例如, 给出数组
[1,2,3,4,5,6,7,8,9,10]
和m = 3,我们可以将其分解为
a=[1,2,3,4][5,6,7][8,9,10]
b=[1,2,3][4,5,6,7][8,9,10]
c=[1,2,3][4,5,6][7,8,9,10]
我们可以认为这些解决方案由对(4,3,3)(3,4,3)和(3,3,4)表示。 我想要一个给定数组,n和m的函数,返回一个随机解决方案并返回具有均匀分布的这些解决方案(这样你就不会比任何其他解决方案更有可能得到一个特定的解决方案)。 (此函数需要适用于n = 50,因此出于性能原因,我们无法通过计算所有可能的解决方案来实现此目的。)
因此,在上面的例子中,这种方法将在三分之一的时间内返回[4,3,3],[3,4,3]在三分之一的时间内返回,[3,3,4]为三分之一当时。
答案 0 :(得分:0)
只是一个想法:
假设m = 3,n = 20。我们能做的就是做到这一点:
最终设定为[6,10,4]
这会有用吗?它也不需要对原始列表进行任何迭代。您唯一的迭代将超过m而不依赖于n。
我可以尝试使变量m更通用(步骤1需要稍微改变,步骤3和5将在循环中)但我相信如果这个解决方案可以接受,你可以解决它给你。 步骤1的重写示例为:
Choose a number between m and n - [m - 1] * m
答案 1 :(得分:0)
这会有用吗?
def randomCollate(item, chunk) {
def collated = item.collate( chunk )
def remainder = collated.reverse().takeWhile { it.size() != chunk }.flatten()
def randomIdx = new Random().nextInt( ( collated - remainder ).size() )
collated[randomIdx] += remainder
collated - [ remainder ]
}
randomCollate( 1..50, 3 )
答案 2 :(得分:0)
我刚才有的另一个想法
我希望你理解我的意思。
答案 3 :(得分:0)
对于每个步骤,允许随机范围n-m*min
(min
在您的示例中为3);然后从该范围中选择一个数字,将min
添加为r
。如果m
为2
,则会返回r
和n-r
的列表。否则返回r
和n-r, m-1
递归调用的结果。洗牌,你有大块的随机大小。
rnd = new Random()
// build the chunk size list to randomly split `n` elements in `m` parts,
// where each part is at least of size `min`
// needs a shuffle afterwards
def s(n,m,min=3) {
def l = n-m*min // the range where we can pick a random offset
def r = min + (l?rnd.nextInt(l):0) // result for this step with optional random part
m==2 ? [r,n-r] : [r]+s(n-r,m-1) // only two remaining? pick result and remainder, or recurse
}
def tests = [[9,3,3],[10,3,3],[27,9,3],[4,2,2]]
1000.times{
tests.each{ n,m,min ->
def r = s(n,m,min)
assert r.sum()==n
assert r.size()==m
assert r.every{ it>= min }
}
}
def items = (0..9).collect() // test list
def slices = s(items.size(),3) // get the chunk sizes
Collections.shuffle(slices) // shuffle the result
// create ranges and use them to get the slices; should be another one or two methods
println slices.inject([sum:0,result:[]]) { r,s -> r.result<<items[((r.sum)..(r.sum+s-1))]; r.sum+=s; r }.result
//=> e.g. [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]