我有一个在Rust中实现Iterator
的结构(尽管问题可以应用于任何语言)来计算数组的组合。使用初始数组创建迭代器,该数组定义数组中每个条目的最大值。迭代器的实际代码仍然是一项正在进行的工作,所以可能有很多地方可以改进。
例如,如果我使用Combo
函数创建Combo::new()
,并且我给set_max
数组[4,3,2,1]
,那么迭代器将生成所有组合长度为4的数组,这样任何条目都不会超过set_max
中给出的条目。
因此,生成的第一个数组是[0,0,0,1]
,然后是[0,0,1,0]
,[0,0,1,1]
,[0,0,2,0]
,[0,0,2,1]
,[0,1,0,0]
,基本上,它一次增加一个条目,直到条目最大化。然后它重置它并开始一次递增两个条目。
我希望这个迭代器在某些时候实现rayon::ParallelIterator
,但首先,我相信我需要一种方法将组合的计算分成两半。
如何找到迭代器的中间点,以便将其分成两部分?
在我找到这个中点后,我对实现split函数有一些想法:添加一个set_min数组,指定一个从中增加条目的起点。但问题的关键是如何找到一般的中点。
#[derive(Clone)]
pub struct Combos {
pub set_max: Vec<usize>,
set_current: Vec<usize>,
size: usize,
}
impl Combos {
pub fn new(set_max: Vec<usize>) -> Combos {
Combos {
set_current: vec![0; set_max.len()],
size: set_max.iter().fold(1, |acc, x| (x + 1) * acc) - 1,
set_max: set_max,
}
}
fn increment_combo(&self, length: usize, combo: &[usize]) -> Vec<usize> {
if let Some(last) = combo.last() {
if *last == self.set_max[length - 1] {
let mut v = self.increment_combo(length - 1, &combo[..length - 1]);
v.push(0);
return v
} else {
let mut v = combo.to_vec();
v[length - 1] = last + 1;
return v
}
} else {
return Vec::new()
}
}
}
impl Iterator for Combos {
type Item=Vec<usize>;
fn next(&mut self) -> Option<Vec<usize>> {
if self.set_current == self.set_max {
return None
}
self.set_current = self.increment_combo(self.set_max.len(), &self.set_current);
return Some(self.set_current.clone())
}
}
答案 0 :(得分:0)
只是将数组的第一个值减半的一半,因为第一个值是算法中最后一个递增的值(最重要的):
[4, 3, 2, 1]
可以这样切割:
first part: [0, 3, 2, 1] -> [1, 3, 2, 1]
second part: [2, 3, 2, 1] -> [3, 3, 2, 1]
因此,这很容易减少一半算法:使用[2, 3, 2, 1]
调用第一部分,使用[4, 3, 2, 1]
调用第二部分:[2, 0, 0, 0]
。