use std::ops::Index;
use std::slice::Iter;
#[derive(Debug, PartialEq, Default, Clone)]
pub struct Marking<T: Ord + Copy> {
values: Vec<(T, usize)>,
}
impl<T> Index<T> for Marking<T>
where
T: Ord + Copy,
{
type Output = usize;
fn index(&self, index: T) -> &Self::Output {
match self.values.binary_search_by(|&v| v.0.cmp(&index)) {
Ok(pos) => &self.values[pos].1,
Err(_) => &0,
}
}
}
pub struct DualMarkingIterator<'m, T>
where
T: Ord + Copy,
{
current_left: usize,
current_right: usize,
left: &'m Marking<T>,
right: &'m Marking<T>,
}
impl<'m, T> Iterator for DualMarkingIterator<'m, T>
where
T: Ord + Copy,
{
type Item = (T, usize, usize);
fn next(&mut self) -> Option<Self::Item> {
if self.current_left >= self.left.len() && self.current_right >= self.right.len() {
None
} else if self.current_left >= self.left.len() {
self.current_right += 1;
Some((
self.right.values[self.current_right - 1].0,
0,
self.right.values[self.current_right - 1].1,
))
} else if self.current_right >= self.right.len() {
self.current_left += 1;
Some((
self.left.values[self.current_left - 1].0,
self.left.values[self.current_left - 1].1,
0,
))
} else if self.left.values[self.current_left].0 == self.right.values[self.current_right].0 {
self.current_left += 1;
self.current_right += 1;
Some((
self.left.values[self.current_left - 1].0,
self.left.values[self.current_left - 1].1,
self.right.values[self.current_right - 1].1,
))
} else if self.left.values[self.current_left].0 < self.right.values[self.current_right].0 {
self.current_left += 1;
Some((
self.left.values[self.current_left - 1].0,
self.left.values[self.current_left - 1].1,
0,
))
} else if self.left.values[self.current_left].0 > self.right.values[self.current_right].0 {
self.current_right += 1;
Some((
self.left.values[self.current_right - 1].0,
0,
self.right.values[self.current_right - 1].1,
))
} else {
None
}
}
}
impl<T> Marking<T>
where
T: Ord + Copy,
{
#[must_use]
pub fn iter(&self) -> Iter<'_, (T, usize)> {
self.values.iter()
}
#[must_use]
pub fn iter_with<'m>(&'m self, other: &'m Self) -> DualMarkingIterator<'m, T> {
DualMarkingIterator {
current_left: 0,
current_right: 0,
left: self,
right: other,
}
}
pub fn clear(&mut self) {
self.values.clear();
}
#[must_use]
pub fn len(&self) -> usize {
self.values.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.values.is_empty()
}
pub fn insert_or_add(&mut self, index: T, weight: usize) {
match self.values.binary_search_by(|&v| v.0.cmp(&index)) {
Ok(pos) => {
if self.values[pos].1 == 0 && weight != 0 {}
self.values[pos].1 += weight;
}
Err(pos) => {
self.values.insert(pos, (index, weight));
}
}
}
pub fn insert_or_min(&mut self, index: T, weight: usize) {
match self.values.binary_search_by(|&v| v.0.cmp(&index)) {
Ok(pos) => {
if weight == 0 && self.values[pos].1 != 0 {}
self.values[pos].1 = self.values[pos].1.min(weight);
}
Err(pos) => {
self.values.insert(pos, (index, weight));
}
}
}
pub fn insert_or_max(&mut self, index: T, weight: usize) {
match self.values.binary_search_by(|&v| v.0.cmp(&index)) {
Ok(pos) => {
self.values[pos].1 = self.values[pos].1.max(weight);
}
Err(pos) => {
self.values.insert(pos, (index, weight));
}
}
}
pub fn delete(&mut self, index: T) {
if let Ok(index) = self.values.binary_search_by(|&v| v.0.cmp(&index)) {
self.values.remove(index);
}
}
}