#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Plan {
pub ends: Vec<i64>,
pub idx_a: Vec<usize>,
pub idx_b: Vec<usize>,
pub fill_a: usize,
pub fill_b: usize,
}
impl Plan {
pub fn num_segments(&self) -> usize {
self.ends.len()
}
pub fn needs_fill_a(&self) -> bool {
self.idx_a.last() == Some(&self.fill_a)
}
pub fn needs_fill_b(&self) -> bool {
self.idx_b.last() == Some(&self.fill_b)
}
pub fn gather_a<A: Clone>(&self, values: &[A], fill: &A) -> Vec<A> {
gather(&self.idx_a, values, fill)
}
pub fn gather_b<B: Clone>(&self, values: &[B], fill: &B) -> Vec<B> {
gather(&self.idx_b, values, fill)
}
}
fn gather<T: Clone>(idx: &[usize], values: &[T], fill: &T) -> Vec<T> {
idx.iter()
.map(|&i| values.get(i).unwrap_or(fill).clone())
.collect()
}
pub fn plan(a: &[i64], b: &[i64]) -> Plan {
let capacity = a.len() + b.len();
let mut out = Plan {
ends: Vec::with_capacity(capacity),
idx_a: Vec::with_capacity(capacity),
idx_b: Vec::with_capacity(capacity),
fill_a: a.len(),
fill_b: b.len(),
};
for (end, i, j) in Segments::new(a, b) {
out.ends.push(end);
out.idx_a.push(i);
out.idx_b.push(j);
}
out
}
pub(crate) struct Segments<'a> {
a: &'a [i64],
b: &'a [i64],
i: usize,
j: usize,
}
impl<'a> Segments<'a> {
pub(crate) fn new(a: &'a [i64], b: &'a [i64]) -> Self {
Segments { a, b, i: 0, j: 0 }
}
}
impl Iterator for Segments<'_> {
type Item = (i64, usize, usize);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let end_a = self.a.get(self.i).copied();
let end_b = self.b.get(self.j).copied();
let end = match (end_a, end_b) {
(None, None) => return None,
(Some(x), None) | (None, Some(x)) => x,
(Some(x), Some(y)) => x.min(y),
};
let item = (end, self.i, self.j);
if end_a == Some(end) {
self.i += 1;
}
if end_b == Some(end) {
self.j += 1;
}
Some(item)
}
}