From c21a9b66ae0cd2a764389a740a94e5d2e77bac7d Mon Sep 17 00:00:00 2001 From: nham Date: Fri, 11 Jul 2014 19:16:34 -0400 Subject: [PATCH 01/13] Add a Multiset trait and an implementation of that trait based on TreeMap. --- src/libcollections/lib.rs | 48 +++++ src/libcollections/treemap.rs | 356 +++++++++++++++++++++++++++++++++- 2 files changed, 403 insertions(+), 1 deletion(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index cce2d14efa9f7..162b45f06a4b6 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -152,6 +152,54 @@ pub trait MutableSet: Set + Mutable { fn remove(&mut self, value: &T) -> bool; } +/// A multiset is an unordered collection of objects in which each object can +/// appear multiple times. This trait represents actions which can be performed +/// on multisets to iterate over them. +pub trait Multiset: Collection { + /// Return the number of occurrences of the value in the multiset. + fn count(&self, value: &T) -> uint; + + /// Return true if the multiset has no elements in common with `other`. + fn is_disjoint(&self, other: &Self) -> bool; + + /// Return true if, for any given element, the number times it occurs in the + /// multiset is not greater than the number of times it occurs in `other`. + fn is_subset(&self, other: &Self) -> bool; + + /// Return true if the value occurs at least once in the multiset. + fn contains(&self, value: &T) -> bool { + self.count(value) > 0u + } + + /// Return true if the multiset is a superset of another. + fn is_superset(&self, other: &Self) -> bool { + other.is_subset(self) + } + + // FIXME: Ideally we would have a method to return the underlying set + // of a multiset. However, currently there's no way to have a trait method + // return a trait. We need something like associated type synonyms (see #5033) +} + +/// This trait represents actions which can be performed on multisets to mutate +/// them. +pub trait MutableMultiset: Multiset + Mutable { + /// Add `n` occurrences of `value` to the multiset. Return true if the value + /// was not already present in the multiset. + fn insert(&mut self, value: T, n: uint) -> bool; + + /// Remove `n` occurrences of `value` from the multiset. If there are less + /// than `n` occurrences, remove all occurrences. Return the number of + /// occurrences removed. + fn remove(&mut self, value: &T, n: uint) -> uint; + + /// Add one occurrence of `value` to the multiset. Return true if the value + /// was not already present in the multiset. + fn insert_one(&mut self, value: T) -> bool { + self.insert(value, 1) + } +} + /// A double-ended sequence that allows querying, insertion and deletion at both /// ends. pub trait Deque : Mutable { diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 1451bf9d7c7bc..116cb9f09a4b9 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -23,7 +23,7 @@ use core::iter; use core::mem::{replace, swap}; use core::ptr; -use {Collection, Mutable, Set, MutableSet, MutableMap, Map}; +use {Collection, Mutable, Set, MutableSet, Multiset, MutableMultiset, MutableMap, Map}; use vec::Vec; // This is implemented as an AA tree, which is a simplified variation of @@ -838,6 +838,222 @@ impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> { } +/// A implementation of the `Multiset` trait on top of the `TreeMap` container. +/// The only requirement is that the type of the elements contained ascribes to +/// the `Ord` trait. +#[deriving(Clone)] +pub struct TreeMultiset { + map: TreeMap, +} + +impl PartialEq for TreeMultiset { + #[inline] + fn eq(&self, other: &TreeMultiset) -> bool { self.map == other.map } +} + +impl PartialOrd for TreeMultiset { + #[inline] + fn partial_cmp(&self, other: &TreeMultiset) -> Option { + self.map.partial_cmp(&other.map) + } +} + +impl Collection for TreeMultiset { + #[inline] + fn len(&self) -> uint { self.map.len() } +} + +impl Mutable for TreeMultiset { + #[inline] + fn clear(&mut self) { self.map.clear() } +} + +impl Extendable for TreeMultiset { + #[inline] + fn extend>(&mut self, mut iter: Iter) { + for elem in iter { + self.insert(elem, 1); + } + } +} + +impl FromIterator for TreeMultiset { + fn from_iter>(iter: Iter) -> TreeMultiset { + let mut mset = TreeMultiset::new(); + mset.extend(iter); + mset + } +} + +impl Multiset for TreeMultiset { + #[inline] + fn count(&self, value: &T) -> uint { + match self.map.find(value) { + None => 0u, + Some(count) => *count + } + } + + fn is_disjoint(&self, other: &TreeMultiset) -> bool { + let mut x = self.iter(); + let mut y = other.iter(); + let mut a = x.next(); + let mut b = y.next(); + while a.is_some() && b.is_some() { + let a1 = a.unwrap(); + let b1 = b.unwrap(); + + match a1.cmp(b1) { + Less => a = x.next(), + Greater => b = y.next(), + Equal => return false, + } + } + true + } + + fn is_subset(&self, other: &TreeMultiset) -> bool { + let mut x = self.iter(); + let mut y = other.iter(); + let mut a = x.next(); + let mut b = y.next(); + while a.is_some() { + if b.is_none() { + return false; + } + + let a1 = a.unwrap(); + let b1 = b.unwrap(); + + match b1.cmp(a1) { + Less => (), + Greater => return false, + Equal => a = x.next(), + } + + b = y.next(); + } + true + } + +} + +impl MutableMultiset for TreeMultiset { + fn insert(&mut self, value: T, n: uint) -> bool { + let curr = self.count(&value); + self.map.insert(value, curr + n) + } + + fn remove(&mut self, value: &T, n: uint) -> uint { + let curr = self.count(value); + + if n >= curr { + self.map.remove(value); + curr + } else { + match self.map.find_mut(value) { + None => 0u, + Some(mult) => { + *mult = curr - n; + n + } + } + } + } + +} + +impl TreeMultiset { + /// Create an empty TreeMultiset + #[inline] + pub fn new() -> TreeMultiset { TreeMultiset {map: TreeMap::new()} } + + /// Get a lazy iterator over the values in the multiset. + /// Requires that it be frozen (immutable). + #[inline] + pub fn iter<'a>(&'a self) -> MultisetItems<'a, T> { + MultisetItems{iter: self.map.iter(), current: None, count: 0 } + } + + /// Get a lazy iterator over the values in the multiset. + /// Requires that it be frozen (immutable). + #[inline] + pub fn rev_iter<'a>(&'a self) -> RevMultisetItems<'a, T> { + RevMultisetItems{iter: self.map.rev_iter(), current: None, count: 0} + } +} + +impl TreeMultiset { + pub fn to_set(&self) -> TreeSet { + let mut set = TreeSet::new(); + for (k, _) in self.map.clone().move_iter() { + set.insert(k); + } + set + } +} + +/// Lazy forward iterator over a multiset +pub struct MultisetItems<'a, T> { + iter: Entries<'a, T, uint>, + current: Option<&'a T>, + count: uint, +} + +/// Lazy backward iterator over a multiset +pub struct RevMultisetItems<'a, T> { + iter: RevEntries<'a, T, uint>, + current: Option<&'a T>, + count: uint, +} + +impl<'a, T> Iterator<&'a T> for MultisetItems<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a T> { + if self.count == 0 { + // Either we've exhausted the multiset or we just need to grab + // the next entry from self.iter + match self.iter.next() { + None => return None, + Some((val, count)) => { + self.current = Some(val); + self.count = *count; + } + } + } + + // Assume here that we will never have an entry with a count of zero. + // This means we have to take care that when we remove the last occurrence + // from a multiset, we must delete the key also. + self.count -= 1; + self.current + } +} + +impl<'a, T> Iterator<&'a T> for RevMultisetItems<'a, T> { + #[inline] + fn next(&mut self) -> Option<&'a T> { + if self.count == 0 { + // Either we've exhausted the multiset or we just need to grab + // the next entry from self.iter + match self.iter.next() { + None => return None, + Some((val, count)) => { + self.current = Some(val); + self.count = *count; + } + } + } + + // Assume here that we will never have an entry with a count of zero. + // This means we have to take care that when we remove the last occurrence + // from a multiset, we must delete the key also. + self.count -= 1; + self.current + } +} + + // Nodes keep track of their level in the tree, starting at 1 in the // leaves and with a red child sharing the level of the parent. #[deriving(Clone)] @@ -1897,3 +2113,141 @@ mod test_set { assert_eq!(format!("{}", empty), "{}".to_string()); } } + +#[cfg(test)] +mod test_mset { + use std::prelude::*; + + use {Multiset, MutableMultiset, Mutable, MutableMap}; + use super::{TreeMap, TreeMultiset}; + + #[test] + fn test_clear() { + let mut s = TreeMultiset::new(); + s.clear(); + assert!(s.insert_one(5i)); + assert!(s.insert_one(12)); + assert!(s.insert_one(19)); + s.clear(); + assert!(!s.contains(&5)); + assert!(!s.contains(&12)); + assert!(!s.contains(&19)); + assert!(s.is_empty()); + } + + #[test] + fn test_disjoint() { + let mut xs = TreeMultiset::new(); + let mut ys = TreeMultiset::new(); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert_one(5i)); + assert!(ys.insert_one(11i)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(xs.insert_one(7)); + assert!(xs.insert_one(19)); + assert!(xs.insert_one(4)); + assert!(ys.insert_one(2)); + assert!(ys.insert_one(-11)); + assert!(xs.is_disjoint(&ys)); + assert!(ys.is_disjoint(&xs)); + assert!(ys.insert_one(7)); + assert!(!ys.is_disjoint(&xs)); + assert!(!xs.is_disjoint(&ys)); + assert!(!xs.insert_one(7)); + assert!(!ys.is_disjoint(&xs)); + assert!(!xs.is_disjoint(&ys)); + } + + #[test] + fn test_subset_and_superset() { + let mut a = TreeMultiset::new(); + assert!(a.insert_one(0i)); + assert!(a.insert_one(5)); + assert!(a.insert_one(11)); + assert!(a.insert_one(7)); + + let mut b = TreeMultiset::new(); + assert!(b.insert_one(0i)); + assert!(b.insert_one(7)); + assert!(b.insert_one(19)); + assert!(b.insert_one(250)); + assert!(b.insert_one(11)); + assert!(b.insert_one(200)); + + assert!(!a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(!b.is_superset(&a)); + + assert!(!a.insert_one(5)); + assert!(b.insert_one(5)); + + assert!(!a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(!b.is_superset(&a)); + + assert!(!b.insert_one(5)); + + assert!(a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(b.is_superset(&a)); + + assert!(!b.insert_one(7)); + assert!(!b.insert_one(7)); + + assert!(a.is_subset(&b)); + assert!(!a.is_superset(&b)); + assert!(!b.is_subset(&a)); + assert!(b.is_superset(&a)); + } + + #[test] + fn test_iterator() { + let mut m = TreeMultiset::new(); + + assert!(m.insert_one(3i)); + assert!(m.insert_one(2)); + assert!(m.insert_one(0)); + assert!(m.insert_one(-2)); + assert!(m.insert_one(4)); + assert!(!m.insert_one(2)); + assert!(m.insert_one(1)); + + let v = vec!(-2i, 0, 1, 2, 2, 3, 4); + for (x, y) in m.iter().zip(v.iter()) { + assert_eq!(*x, *y); + } + } + + #[test] + fn test_rev_iter() { + let mut m = TreeMultiset::new(); + + assert!(m.insert_one(3i)); + assert!(m.insert_one(2)); + assert!(m.insert_one(0)); + assert!(m.insert_one(-2)); + assert!(m.insert_one(4)); + assert!(!m.insert_one(2)); + assert!(m.insert_one(1)); + + let v = vec!(4i, 3, 2, 2, 1, 0, -2); + for (x, y) in m.rev_iter().zip(v.iter()) { + assert_eq!(*x, *y); + } + } + + #[test] + fn test_clone_eq() { + let mut m = TreeMultiset::new(); + + m.insert_one(1i); + m.insert_one(2); + + assert!(m.clone() == m); + } +} From 0976d479ce4af4facdc503f3fddab992b363c45c Mon Sep 17 00:00:00 2001 From: nham Date: Sat, 12 Jul 2014 11:22:31 -0400 Subject: [PATCH 02/13] Change difference/symmetric-differenc/intersection/union iterators to take iterator parameter. This allows them to be used for both TreeSet and TreeMultiset. --- src/libcollections/treemap.rs | 150 +++++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 20 deletions(-) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 116cb9f09a4b9..9088484055a3c 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -714,24 +714,26 @@ impl TreeSet { } /// Visit the values (in-order) representing the difference - pub fn difference<'a>(&'a self, other: &'a TreeSet) -> DifferenceItems<'a, T> { + pub fn difference<'a>(&'a self, other: &'a TreeSet) + -> DifferenceItems<'a, T, SetItems<'a, T>> { DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} } /// Visit the values (in-order) representing the symmetric difference pub fn symmetric_difference<'a>(&'a self, other: &'a TreeSet) - -> SymDifferenceItems<'a, T> { + -> SymDifferenceItems<'a, T, SetItems<'a, T>> { SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} } /// Visit the values (in-order) representing the intersection pub fn intersection<'a>(&'a self, other: &'a TreeSet) - -> IntersectionItems<'a, T> { + -> IntersectionItems<'a, T, SetItems<'a, T>> { IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} } /// Visit the values (in-order) representing the union - pub fn union<'a>(&'a self, other: &'a TreeSet) -> UnionItems<'a, T> { + pub fn union<'a>(&'a self, other: &'a TreeSet) + -> UnionItems<'a, T, SetItems<'a, T>> { UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} } } @@ -750,27 +752,27 @@ pub struct RevSetItems<'a, T> { pub type MoveSetItems = iter::Map<'static, (T, ()), T, MoveEntries>; /// Lazy iterator producing elements in the set difference (in-order) -pub struct DifferenceItems<'a, T> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, +pub struct DifferenceItems<'a, T, I> { + a: Peekable<&'a T, I>, + b: Peekable<&'a T, I>, } /// Lazy iterator producing elements in the set symmetric difference (in-order) -pub struct SymDifferenceItems<'a, T> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, +pub struct SymDifferenceItems<'a, T, I> { + a: Peekable<&'a T, I>, + b: Peekable<&'a T, I>, } /// Lazy iterator producing elements in the set intersection (in-order) -pub struct IntersectionItems<'a, T> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, +pub struct IntersectionItems<'a, T, I> { + a: Peekable<&'a T, I>, + b: Peekable<&'a T, I>, } /// Lazy iterator producing elements in the set union (in-order) -pub struct UnionItems<'a, T> { - a: Peekable<&'a T, SetItems<'a, T>>, - b: Peekable<&'a T, SetItems<'a, T>>, +pub struct UnionItems<'a, T, I> { + a: Peekable<&'a T, I>, + b: Peekable<&'a T, I>, } /// Compare `x` and `y`, but return `short` if x is None and `long` if y is None @@ -783,7 +785,7 @@ fn cmp_opt(x: Option<&T>, y: Option<&T>, } } -impl<'a, T: Ord> Iterator<&'a T> for DifferenceItems<'a, T> { +impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for DifferenceItems<'a, T, I> { fn next(&mut self) -> Option<&'a T> { loop { match cmp_opt(self.a.peek(), self.b.peek(), Less, Less) { @@ -795,7 +797,7 @@ impl<'a, T: Ord> Iterator<&'a T> for DifferenceItems<'a, T> { } } -impl<'a, T: Ord> Iterator<&'a T> for SymDifferenceItems<'a, T> { +impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for SymDifferenceItems<'a, T, I> { fn next(&mut self) -> Option<&'a T> { loop { match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { @@ -807,7 +809,7 @@ impl<'a, T: Ord> Iterator<&'a T> for SymDifferenceItems<'a, T> { } } -impl<'a, T: Ord> Iterator<&'a T> for IntersectionItems<'a, T> { +impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for IntersectionItems<'a, T, I> { fn next(&mut self) -> Option<&'a T> { loop { let o_cmp = match (self.a.peek(), self.b.peek()) { @@ -825,7 +827,7 @@ impl<'a, T: Ord> Iterator<&'a T> for IntersectionItems<'a, T> { } } -impl<'a, T: Ord> Iterator<&'a T> for UnionItems<'a, T> { +impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for UnionItems<'a, T, I> { fn next(&mut self) -> Option<&'a T> { loop { match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { @@ -981,6 +983,30 @@ impl TreeMultiset { pub fn rev_iter<'a>(&'a self) -> RevMultisetItems<'a, T> { RevMultisetItems{iter: self.map.rev_iter(), current: None, count: 0} } + + /// Visit the values (in-order) representing the difference + pub fn difference<'a>(&'a self, other: &'a TreeMultiset) + -> DifferenceItems<'a, T, MultisetItems<'a, T>> { + DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visit the values (in-order) representing the symmetric difference + pub fn symmetric_difference<'a>(&'a self, other: &'a TreeMultiset) + -> SymDifferenceItems<'a, T, MultisetItems<'a, T>> { + SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visit the values (in-order) representing the intersection + pub fn intersection<'a>(&'a self, other: &'a TreeMultiset) + -> IntersectionItems<'a, T, MultisetItems<'a, T>> { + IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visit the values (in-order) representing the union + pub fn union<'a>(&'a self, other: &'a TreeMultiset) + -> UnionItems<'a, T, MultisetItems<'a, T>> { + UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } } impl TreeMultiset { @@ -2250,4 +2276,88 @@ mod test_mset { assert!(m.clone() == m); } + + fn check(a: &[int], + b: &[int], + expected: &[int], + f: |&TreeMultiset, &TreeMultiset, f: |&int| -> bool| -> bool) { + let mut set_a = TreeMultiset::new(); + let mut set_b = TreeMultiset::new(); + + for x in a.iter() { set_a.insert_one(*x); } + for y in b.iter() { set_b.insert_one(*y); } + + let mut i = 0; + f(&set_a, &set_b, |x| { + assert_eq!(*x, expected[i]); + i += 1; + true + }); + assert_eq!(i, expected.len()); + } + + #[test] + fn test_intersection() { + fn check_intersection(a: &[int], b: &[int], expected: &[int]) { + check(a, b, expected, |x, y, f| x.intersection(y).all(f)) + } + + check_intersection([], [], []); + check_intersection([1, 2, 3, 2], [], []); + check_intersection([], [1, 2, 3, 2], []); + check_intersection([2], [1, 2, 3], [2]); + check_intersection([2, 2], [1, 2, 3, 2], [2, 2]); + check_intersection([1, 2, 3, 2], [2, 2], [2, 2]); + check_intersection([11, 5, 5, 1, 3, 77, 103, 5, -5, 1, 1, 77], + [2, 11, 77, -9, -42, 5, 3, 77, 2, 5], + [3, 5, 5, 11, 77, 77]); + } + + #[test] + fn test_difference() { + fn check_difference(a: &[int], b: &[int], expected: &[int]) { + check(a, b, expected, |x, y, f| x.difference(y).all(f)) + } + + check_difference([], [], []); + check_difference([1, 12], [], [1, 12]); + check_difference([1, 12, 1], [], [1, 1, 12]); + check_difference([], [1, 2, 2, 3, 9], []); + check_difference([1, 3, 3, 3, 5, 9, 11], + [3, 9, 3], + [1, 3, 5, 11]); + check_difference([-5, 11, 22, 33, 40, 42], + [-12, -5, 14, 23, 34, 38, 39, 50], + [11, 22, 33, 40, 42]); + } + + #[test] + fn test_symmetric_difference() { + fn check_symmetric_difference(a: &[int], b: &[int], + expected: &[int]) { + check(a, b, expected, |x, y, f| x.symmetric_difference(y).all(f)) + } + + check_symmetric_difference([], [], []); + check_symmetric_difference([1, 1, 2, 3], [2], [1, 1, 3]); + check_symmetric_difference([2, 2], [1, 2, 2, 3], [1, 3]); + check_symmetric_difference([1, 3, 5, 9, 11], + [-2, 3, 9, 14, 22], + [-2, 1, 5, 11, 14, 22]); + } + + #[test] + fn test_union() { + fn check_union(a: &[int], b: &[int], + expected: &[int]) { + check(a, b, expected, |x, y, f| x.union(y).all(f)) + } + + check_union([], [], []); + check_union([1, 2, 2, 3], [2], [1, 2, 2, 3]); + check_union([2, 2, 2], [1, 2, 2, 3], [1, 2, 2, 2, 3]); + check_union([1, 3, 5, 9, 11, 16, 19, 24], + [-2, 1, 5, 9, 13, 19], + [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); + } } From 2d22dcf4689e75881569bf245d07bef8721d20b7 Mon Sep 17 00:00:00 2001 From: nham Date: Sat, 12 Jul 2014 14:13:40 -0400 Subject: [PATCH 03/13] Various additions. Add remove_one() method to MutableMultiset. Implement Show and Default for TreeMultiset. Add tests for count() and the Show implementation. --- src/libcollections/lib.rs | 6 +++++ src/libcollections/treemap.rs | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 162b45f06a4b6..2280ce66cb3e0 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -198,6 +198,12 @@ pub trait MutableMultiset: Multiset + Mutable { fn insert_one(&mut self, value: T) -> bool { self.insert(value, 1) } + + /// Remove one occurrence of `value` from the multiset. Return true if the + /// value was present in the multiset. + fn remove_one(&mut self, value: &T) -> bool { + self.remove(value, 1) > 0u + } } /// A double-ended sequence that allows querying, insertion and deletion at both diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 9088484055a3c..acda19879f27f 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -860,6 +860,19 @@ impl PartialOrd for TreeMultiset { } } +impl Show for TreeMultiset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", *x)); + } + + write!(f, "}}") + } +} + impl Collection for TreeMultiset { #[inline] fn len(&self) -> uint { self.map.len() } @@ -965,6 +978,11 @@ impl MutableMultiset for TreeMultiset { } +impl Default for TreeMultiset { + #[inline] + fn default() -> TreeMultiset { TreeMultiset::new() } +} + impl TreeMultiset { /// Create an empty TreeMultiset #[inline] @@ -2161,6 +2179,25 @@ mod test_mset { assert!(s.is_empty()); } + #[test] + fn test_count() { + let mut m = TreeMultiset::new(); + assert!(m.insert_one(1i)); + assert!(m.count(&1) == 1); + assert!(!m.insert_one(1i)); + assert!(m.count(&1) == 2); + + assert!(m.count(&2) == 0); + assert!(m.insert(2i, 4)); + assert!(m.count(&2) == 4); + assert!(m.remove(&2, 3) == 3); + assert!(m.count(&2) == 1); + assert!(m.remove_one(&2)); + assert!(m.count(&2) == 0); + assert!(!m.remove_one(&2)); + assert!(m.count(&2) == 0); + } + #[test] fn test_disjoint() { let mut xs = TreeMultiset::new(); @@ -2360,4 +2397,18 @@ mod test_mset { [-2, 1, 5, 9, 13, 19], [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); } + + #[test] + fn test_show() { + let mut set: TreeMultiset = TreeMultiset::new(); + let empty: TreeMultiset = TreeMultiset::new(); + + set.insert_one(1); + set.insert(2, 3); + + let set_str = format!("{}", set); + + assert!(set_str == "{1, 2, 2, 2}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } } From b527a30ffcf028813ed74425df4e83dc3c8b5a22 Mon Sep 17 00:00:00 2001 From: nham Date: Sun, 13 Jul 2014 16:37:39 -0400 Subject: [PATCH 04/13] Change TreeMultiset len() to return the number of occurrences. The previous version returned the number of distinct values. --- src/libcollections/treemap.rs | 40 +++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index acda19879f27f..eb6e38cf35aad 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -846,6 +846,7 @@ impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for UnionItems<'a, T, I> { #[deriving(Clone)] pub struct TreeMultiset { map: TreeMap, + length: uint, } impl PartialEq for TreeMultiset { @@ -875,12 +876,15 @@ impl Show for TreeMultiset { impl Collection for TreeMultiset { #[inline] - fn len(&self) -> uint { self.map.len() } + fn len(&self) -> uint { self.length } } impl Mutable for TreeMultiset { #[inline] - fn clear(&mut self) { self.map.clear() } + fn clear(&mut self) { + self.map.clear(); + self.length = 0; + } } impl Extendable for TreeMultiset { @@ -956,6 +960,7 @@ impl Multiset for TreeMultiset { impl MutableMultiset for TreeMultiset { fn insert(&mut self, value: T, n: uint) -> bool { let curr = self.count(&value); + self.length += n; self.map.insert(value, curr + n) } @@ -964,18 +969,19 @@ impl MutableMultiset for TreeMultiset { if n >= curr { self.map.remove(value); + self.length -= curr; curr } else { match self.map.find_mut(value) { None => 0u, Some(mult) => { + self.length -= n; *mult = curr - n; n } } } } - } impl Default for TreeMultiset { @@ -986,7 +992,10 @@ impl Default for TreeMultiset { impl TreeMultiset { /// Create an empty TreeMultiset #[inline] - pub fn new() -> TreeMultiset { TreeMultiset {map: TreeMap::new()} } + pub fn new() -> TreeMultiset { TreeMultiset {map: TreeMap::new(), length: 0} } + + /// Get the number of distinct values in the multiset + pub fn num_distinct(&self) -> uint { self.map.len() } /// Get a lazy iterator over the values in the multiset. /// Requires that it be frozen (immutable). @@ -2165,6 +2174,29 @@ mod test_mset { use {Multiset, MutableMultiset, Mutable, MutableMap}; use super::{TreeMap, TreeMultiset}; + #[test] + fn test_len() { + let mut s = TreeMultiset::new(); + assert!(s.len() == 0); + assert!(s.insert_one(1i)); + assert!(s.len() == 1); + assert!(s.insert(3, 5)); + assert!(s.len() == 6); + assert!(s.insert(7, 2)); + assert!(s.len() == 8); + + assert!(s.remove_one(&7)); + assert!(s.len() == 7); + assert!(s.remove_one(&7)); + assert!(s.len() == 6); + assert!(!s.remove_one(&7)); + assert!(s.len() == 6); + assert!(s.remove(&3, 3) == 3); + assert!(s.len() == 3); + assert!(s.remove(&3, 8) == 2); + assert!(s.len() == 1); + } + #[test] fn test_clear() { let mut s = TreeMultiset::new(); From 48add65102ae7e9266c87a65f76c3696e1a465e8 Mon Sep 17 00:00:00 2001 From: nham Date: Mon, 14 Jul 2014 00:23:39 -0400 Subject: [PATCH 05/13] Make TreeMultiset.extend() use insert_one --- src/libcollections/treemap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index eb6e38cf35aad..dc8c6d8870edc 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -891,7 +891,7 @@ impl Extendable for TreeMultiset { #[inline] fn extend>(&mut self, mut iter: Iter) { for elem in iter { - self.insert(elem, 1); + self.insert_one(elem); } } } From 4592fdcbcfac492d22d26bb8bbd10d6d83c675b0 Mon Sep 17 00:00:00 2001 From: nham Date: Mon, 14 Jul 2014 00:27:56 -0400 Subject: [PATCH 06/13] Add sum operation to TreeMultiset --- src/libcollections/treemap.rs | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index dc8c6d8870edc..5a86be9e34a14 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -763,6 +763,12 @@ pub struct SymDifferenceItems<'a, T, I> { b: Peekable<&'a T, I>, } +/// Lazy iterator producing elements in the multiset sum (in-order) +pub struct SumItems<'a, T, I> { + a: Peekable<&'a T, I>, + b: Peekable<&'a T, I>, +} + /// Lazy iterator producing elements in the set intersection (in-order) pub struct IntersectionItems<'a, T, I> { a: Peekable<&'a T, I>, @@ -809,6 +815,18 @@ impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for SymDifferenceItems<'a, } } +impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for SumItems<'a, T, I> { + fn next(&mut self) -> Option<&'a T> { + loop { + match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { + Less => return self.a.next(), + Equal => return self.a.next(), + Greater => return self.b.next(), + } + } + } +} + impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for IntersectionItems<'a, T, I> { fn next(&mut self) -> Option<&'a T> { loop { @@ -1023,6 +1041,12 @@ impl TreeMultiset { SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} } + /// Visit the values (in-order) representing the multiset sum + pub fn sum<'a>(&'a self, other: &'a TreeMultiset) + -> SumItems<'a, T, MultisetItems<'a, T>> { + SumItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + /// Visit the values (in-order) representing the intersection pub fn intersection<'a>(&'a self, other: &'a TreeMultiset) -> IntersectionItems<'a, T, MultisetItems<'a, T>> { @@ -2415,6 +2439,21 @@ mod test_mset { [-2, 1, 5, 11, 14, 22]); } + #[test] + fn test_sum() { + fn check_sum(a: &[int], b: &[int], + expected: &[int]) { + check(a, b, expected, |x, y, f| x.sum(y).all(f)) + } + + check_sum([], [], []); + check_sum([1, 2, 2, 3], [2], [1, 2, 2, 2, 3]); + check_sum([2, 2], [1, 2, 2, 3], [1, 2, 2, 2, 2, 3]); + check_sum([1, 3, 5, 9, 11, 16, 19, 24], + [-2, 1, 5, 9, 13, 19], + [-2, 1, 1, 3, 5, 5, 9, 9, 11, 13, 16, 19, 19, 24]); + } + #[test] fn test_union() { fn check_union(a: &[int], b: &[int], From d7c2a91b22405f6e49885d7f1b5200dab508c566 Mon Sep 17 00:00:00 2001 From: nham Date: Mon, 14 Jul 2014 01:06:41 -0400 Subject: [PATCH 07/13] Add test_from_iter to TreeMultiset --- src/libcollections/treemap.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 5a86be9e34a14..70deac3eb5949 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -2469,6 +2469,23 @@ mod test_mset { [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); } + #[test] + fn test_from_iter() { + let xs = [1i, 2, 3, 3, 3, 4, 5, 4, 6, 7, 8, 9]; + + let set: TreeMultiset = xs.iter().map(|&x| x).collect(); + + for x in xs.iter() { + if *x == 3 { + assert!(set.count(x) == 3); + } else if *x == 4 { + assert!(set.count(x) == 2); + } else { + assert!(set.count(x) == 1); + } + } + } + #[test] fn test_show() { let mut set: TreeMultiset = TreeMultiset::new(); From ac30b874223eec795a7dbc904faa71e94093c383 Mon Sep 17 00:00:00 2001 From: nham Date: Wed, 16 Jul 2014 14:59:38 -0400 Subject: [PATCH 08/13] Rename [insert|remove]_one to [insert|remove] and [insert|remove] to [insert|remove]_many --- src/libcollections/lib.rs | 12 ++-- src/libcollections/treemap.rs | 128 +++++++++++++++++----------------- 2 files changed, 70 insertions(+), 70 deletions(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 2280ce66cb3e0..dd935dd40480c 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -186,23 +186,23 @@ pub trait Multiset: Collection { pub trait MutableMultiset: Multiset + Mutable { /// Add `n` occurrences of `value` to the multiset. Return true if the value /// was not already present in the multiset. - fn insert(&mut self, value: T, n: uint) -> bool; + fn insert_many(&mut self, value: T, n: uint) -> bool; /// Remove `n` occurrences of `value` from the multiset. If there are less /// than `n` occurrences, remove all occurrences. Return the number of /// occurrences removed. - fn remove(&mut self, value: &T, n: uint) -> uint; + fn remove_many(&mut self, value: &T, n: uint) -> uint; /// Add one occurrence of `value` to the multiset. Return true if the value /// was not already present in the multiset. - fn insert_one(&mut self, value: T) -> bool { - self.insert(value, 1) + fn insert(&mut self, value: T) -> bool { + self.insert_many(value, 1) } /// Remove one occurrence of `value` from the multiset. Return true if the /// value was present in the multiset. - fn remove_one(&mut self, value: &T) -> bool { - self.remove(value, 1) > 0u + fn remove(&mut self, value: &T) -> bool { + self.remove_many(value, 1) > 0u } } diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 70deac3eb5949..cc96fcad4a023 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -909,7 +909,7 @@ impl Extendable for TreeMultiset { #[inline] fn extend>(&mut self, mut iter: Iter) { for elem in iter { - self.insert_one(elem); + self.insert(elem); } } } @@ -976,13 +976,13 @@ impl Multiset for TreeMultiset { } impl MutableMultiset for TreeMultiset { - fn insert(&mut self, value: T, n: uint) -> bool { + fn insert_many(&mut self, value: T, n: uint) -> bool { let curr = self.count(&value); self.length += n; self.map.insert(value, curr + n) } - fn remove(&mut self, value: &T, n: uint) -> uint { + fn remove_many(&mut self, value: &T, n: uint) -> uint { let curr = self.count(value); if n >= curr { @@ -2202,22 +2202,22 @@ mod test_mset { fn test_len() { let mut s = TreeMultiset::new(); assert!(s.len() == 0); - assert!(s.insert_one(1i)); + assert!(s.insert(1i)); assert!(s.len() == 1); - assert!(s.insert(3, 5)); + assert!(s.insert_many(3, 5)); assert!(s.len() == 6); - assert!(s.insert(7, 2)); + assert!(s.insert_many(7, 2)); assert!(s.len() == 8); - assert!(s.remove_one(&7)); + assert!(s.remove(&7)); assert!(s.len() == 7); - assert!(s.remove_one(&7)); + assert!(s.remove(&7)); assert!(s.len() == 6); - assert!(!s.remove_one(&7)); + assert!(!s.remove(&7)); assert!(s.len() == 6); - assert!(s.remove(&3, 3) == 3); + assert!(s.remove_many(&3, 3) == 3); assert!(s.len() == 3); - assert!(s.remove(&3, 8) == 2); + assert!(s.remove_many(&3, 8) == 2); assert!(s.len() == 1); } @@ -2225,9 +2225,9 @@ mod test_mset { fn test_clear() { let mut s = TreeMultiset::new(); s.clear(); - assert!(s.insert_one(5i)); - assert!(s.insert_one(12)); - assert!(s.insert_one(19)); + assert!(s.insert(5i)); + assert!(s.insert(12)); + assert!(s.insert(19)); s.clear(); assert!(!s.contains(&5)); assert!(!s.contains(&12)); @@ -2238,19 +2238,19 @@ mod test_mset { #[test] fn test_count() { let mut m = TreeMultiset::new(); - assert!(m.insert_one(1i)); + assert!(m.insert(1i)); assert!(m.count(&1) == 1); - assert!(!m.insert_one(1i)); + assert!(!m.insert(1i)); assert!(m.count(&1) == 2); assert!(m.count(&2) == 0); - assert!(m.insert(2i, 4)); + assert!(m.insert_many(2i, 4)); assert!(m.count(&2) == 4); - assert!(m.remove(&2, 3) == 3); + assert!(m.remove_many(&2, 3) == 3); assert!(m.count(&2) == 1); - assert!(m.remove_one(&2)); + assert!(m.remove(&2)); assert!(m.count(&2) == 0); - assert!(!m.remove_one(&2)); + assert!(!m.remove(&2)); assert!(m.count(&2) == 0); } @@ -2260,21 +2260,21 @@ mod test_mset { let mut ys = TreeMultiset::new(); assert!(xs.is_disjoint(&ys)); assert!(ys.is_disjoint(&xs)); - assert!(xs.insert_one(5i)); - assert!(ys.insert_one(11i)); + assert!(xs.insert(5i)); + assert!(ys.insert(11i)); assert!(xs.is_disjoint(&ys)); assert!(ys.is_disjoint(&xs)); - assert!(xs.insert_one(7)); - assert!(xs.insert_one(19)); - assert!(xs.insert_one(4)); - assert!(ys.insert_one(2)); - assert!(ys.insert_one(-11)); + assert!(xs.insert(7)); + assert!(xs.insert(19)); + assert!(xs.insert(4)); + assert!(ys.insert(2)); + assert!(ys.insert(-11)); assert!(xs.is_disjoint(&ys)); assert!(ys.is_disjoint(&xs)); - assert!(ys.insert_one(7)); + assert!(ys.insert(7)); assert!(!ys.is_disjoint(&xs)); assert!(!xs.is_disjoint(&ys)); - assert!(!xs.insert_one(7)); + assert!(!xs.insert(7)); assert!(!ys.is_disjoint(&xs)); assert!(!xs.is_disjoint(&ys)); } @@ -2282,41 +2282,41 @@ mod test_mset { #[test] fn test_subset_and_superset() { let mut a = TreeMultiset::new(); - assert!(a.insert_one(0i)); - assert!(a.insert_one(5)); - assert!(a.insert_one(11)); - assert!(a.insert_one(7)); + assert!(a.insert(0i)); + assert!(a.insert(5)); + assert!(a.insert(11)); + assert!(a.insert(7)); let mut b = TreeMultiset::new(); - assert!(b.insert_one(0i)); - assert!(b.insert_one(7)); - assert!(b.insert_one(19)); - assert!(b.insert_one(250)); - assert!(b.insert_one(11)); - assert!(b.insert_one(200)); + assert!(b.insert(0i)); + assert!(b.insert(7)); + assert!(b.insert(19)); + assert!(b.insert(250)); + assert!(b.insert(11)); + assert!(b.insert(200)); assert!(!a.is_subset(&b)); assert!(!a.is_superset(&b)); assert!(!b.is_subset(&a)); assert!(!b.is_superset(&a)); - assert!(!a.insert_one(5)); - assert!(b.insert_one(5)); + assert!(!a.insert(5)); + assert!(b.insert(5)); assert!(!a.is_subset(&b)); assert!(!a.is_superset(&b)); assert!(!b.is_subset(&a)); assert!(!b.is_superset(&a)); - assert!(!b.insert_one(5)); + assert!(!b.insert(5)); assert!(a.is_subset(&b)); assert!(!a.is_superset(&b)); assert!(!b.is_subset(&a)); assert!(b.is_superset(&a)); - assert!(!b.insert_one(7)); - assert!(!b.insert_one(7)); + assert!(!b.insert(7)); + assert!(!b.insert(7)); assert!(a.is_subset(&b)); assert!(!a.is_superset(&b)); @@ -2328,13 +2328,13 @@ mod test_mset { fn test_iterator() { let mut m = TreeMultiset::new(); - assert!(m.insert_one(3i)); - assert!(m.insert_one(2)); - assert!(m.insert_one(0)); - assert!(m.insert_one(-2)); - assert!(m.insert_one(4)); - assert!(!m.insert_one(2)); - assert!(m.insert_one(1)); + assert!(m.insert(3i)); + assert!(m.insert(2)); + assert!(m.insert(0)); + assert!(m.insert(-2)); + assert!(m.insert(4)); + assert!(!m.insert(2)); + assert!(m.insert(1)); let v = vec!(-2i, 0, 1, 2, 2, 3, 4); for (x, y) in m.iter().zip(v.iter()) { @@ -2346,13 +2346,13 @@ mod test_mset { fn test_rev_iter() { let mut m = TreeMultiset::new(); - assert!(m.insert_one(3i)); - assert!(m.insert_one(2)); - assert!(m.insert_one(0)); - assert!(m.insert_one(-2)); - assert!(m.insert_one(4)); - assert!(!m.insert_one(2)); - assert!(m.insert_one(1)); + assert!(m.insert(3i)); + assert!(m.insert(2)); + assert!(m.insert(0)); + assert!(m.insert(-2)); + assert!(m.insert(4)); + assert!(!m.insert(2)); + assert!(m.insert(1)); let v = vec!(4i, 3, 2, 2, 1, 0, -2); for (x, y) in m.rev_iter().zip(v.iter()) { @@ -2364,8 +2364,8 @@ mod test_mset { fn test_clone_eq() { let mut m = TreeMultiset::new(); - m.insert_one(1i); - m.insert_one(2); + m.insert(1i); + m.insert(2); assert!(m.clone() == m); } @@ -2377,8 +2377,8 @@ mod test_mset { let mut set_a = TreeMultiset::new(); let mut set_b = TreeMultiset::new(); - for x in a.iter() { set_a.insert_one(*x); } - for y in b.iter() { set_b.insert_one(*y); } + for x in a.iter() { set_a.insert(*x); } + for y in b.iter() { set_b.insert(*y); } let mut i = 0; f(&set_a, &set_b, |x| { @@ -2491,8 +2491,8 @@ mod test_mset { let mut set: TreeMultiset = TreeMultiset::new(); let empty: TreeMultiset = TreeMultiset::new(); - set.insert_one(1); - set.insert(2, 3); + set.insert(1); + set.insert_many(2, 3); let set_str = format!("{}", set); From 8bdcb1beafa75823ec28696317b9bdc0c9068e1d Mon Sep 17 00:00:00 2001 From: nham Date: Wed, 16 Jul 2014 15:11:21 -0400 Subject: [PATCH 09/13] Make TreeMultiset implement Hash --- src/libcollections/treemap.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index cc96fcad4a023..88ea1be22dd93 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -879,6 +879,14 @@ impl PartialOrd for TreeMultiset { } } +impl> Hash for TreeMultiset { + fn hash(&self, state: &mut S) { + for elt in self.iter() { + elt.hash(state); + } + } +} + impl Show for TreeMultiset { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "{{")); @@ -2194,6 +2202,7 @@ mod test_set { #[cfg(test)] mod test_mset { use std::prelude::*; + use std::hash; use {Multiset, MutableMultiset, Mutable, MutableMap}; use super::{TreeMap, TreeMultiset}; @@ -2370,6 +2379,22 @@ mod test_mset { assert!(m.clone() == m); } + #[test] + fn test_hash() { + let mut x = TreeMultiset::new(); + let mut y = TreeMultiset::new(); + + x.insert(1i); + x.insert(2); + x.insert(3); + + y.insert(3i); + y.insert(2); + y.insert(1); + + assert!(hash::hash(&x) == hash::hash(&y)); + } + fn check(a: &[int], b: &[int], expected: &[int], From 3e7c70b4bf783cc2c72b6187091062dff802f02e Mon Sep 17 00:00:00 2001 From: nham Date: Wed, 16 Jul 2014 19:42:36 -0400 Subject: [PATCH 10/13] Remove the Multiset and MutableMultiset traits. The collections crate is still in flux, so we are holding off on deciding the design of this trait. --- src/libcollections/lib.rs | 54 ----------- src/libcollections/treemap.rs | 166 +++++++++++++++++++++------------- 2 files changed, 101 insertions(+), 119 deletions(-) diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index dd935dd40480c..cce2d14efa9f7 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -152,60 +152,6 @@ pub trait MutableSet: Set + Mutable { fn remove(&mut self, value: &T) -> bool; } -/// A multiset is an unordered collection of objects in which each object can -/// appear multiple times. This trait represents actions which can be performed -/// on multisets to iterate over them. -pub trait Multiset: Collection { - /// Return the number of occurrences of the value in the multiset. - fn count(&self, value: &T) -> uint; - - /// Return true if the multiset has no elements in common with `other`. - fn is_disjoint(&self, other: &Self) -> bool; - - /// Return true if, for any given element, the number times it occurs in the - /// multiset is not greater than the number of times it occurs in `other`. - fn is_subset(&self, other: &Self) -> bool; - - /// Return true if the value occurs at least once in the multiset. - fn contains(&self, value: &T) -> bool { - self.count(value) > 0u - } - - /// Return true if the multiset is a superset of another. - fn is_superset(&self, other: &Self) -> bool { - other.is_subset(self) - } - - // FIXME: Ideally we would have a method to return the underlying set - // of a multiset. However, currently there's no way to have a trait method - // return a trait. We need something like associated type synonyms (see #5033) -} - -/// This trait represents actions which can be performed on multisets to mutate -/// them. -pub trait MutableMultiset: Multiset + Mutable { - /// Add `n` occurrences of `value` to the multiset. Return true if the value - /// was not already present in the multiset. - fn insert_many(&mut self, value: T, n: uint) -> bool; - - /// Remove `n` occurrences of `value` from the multiset. If there are less - /// than `n` occurrences, remove all occurrences. Return the number of - /// occurrences removed. - fn remove_many(&mut self, value: &T, n: uint) -> uint; - - /// Add one occurrence of `value` to the multiset. Return true if the value - /// was not already present in the multiset. - fn insert(&mut self, value: T) -> bool { - self.insert_many(value, 1) - } - - /// Remove one occurrence of `value` from the multiset. Return true if the - /// value was present in the multiset. - fn remove(&mut self, value: &T) -> bool { - self.remove_many(value, 1) > 0u - } -} - /// A double-ended sequence that allows querying, insertion and deletion at both /// ends. pub trait Deque : Mutable { diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 88ea1be22dd93..3dd315ea93664 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -23,7 +23,7 @@ use core::iter; use core::mem::{replace, swap}; use core::ptr; -use {Collection, Mutable, Set, MutableSet, Multiset, MutableMultiset, MutableMap, Map}; +use {Collection, Mutable, Set, MutableSet, MutableMap, Map}; use vec::Vec; // This is implemented as an AA tree, which is a simplified variation of @@ -858,9 +858,9 @@ impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for UnionItems<'a, T, I> { } -/// A implementation of the `Multiset` trait on top of the `TreeMap` container. -/// The only requirement is that the type of the elements contained ascribes to -/// the `Ord` trait. +/// A implementation of a multiset on top of the `TreeMap` container. The only +/// requirement is that the type of the elements contained ascribes to the +/// `Ord` trait. #[deriving(Clone)] pub struct TreeMultiset { map: TreeMap, @@ -930,16 +930,74 @@ impl FromIterator for TreeMultiset { } } -impl Multiset for TreeMultiset { +impl Default for TreeMultiset { + #[inline] + fn default() -> TreeMultiset { TreeMultiset::new() } +} + +impl TreeMultiset { + /// Create an empty TreeMultiset + #[inline] + pub fn new() -> TreeMultiset { TreeMultiset {map: TreeMap::new(), length: 0} } + + /// Get the number of distinct values in the multiset + pub fn num_distinct(&self) -> uint { self.map.len() } + + /// Get a lazy iterator over the values in the multiset. + /// Requires that it be frozen (immutable). #[inline] - fn count(&self, value: &T) -> uint { + pub fn iter<'a>(&'a self) -> MultisetItems<'a, T> { + MultisetItems{iter: self.map.iter(), current: None, count: 0 } + } + + /// Get a lazy iterator over the values in the multiset. + /// Requires that it be frozen (immutable). + #[inline] + pub fn rev_iter<'a>(&'a self) -> RevMultisetItems<'a, T> { + RevMultisetItems{iter: self.map.rev_iter(), current: None, count: 0} + } + + /// Visit the values (in-order) representing the difference + pub fn difference<'a>(&'a self, other: &'a TreeMultiset) + -> DifferenceItems<'a, T, MultisetItems<'a, T>> { + DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visit the values (in-order) representing the symmetric difference + pub fn symmetric_difference<'a>(&'a self, other: &'a TreeMultiset) + -> SymDifferenceItems<'a, T, MultisetItems<'a, T>> { + SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visit the values (in-order) representing the multiset sum + pub fn sum<'a>(&'a self, other: &'a TreeMultiset) + -> SumItems<'a, T, MultisetItems<'a, T>> { + SumItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visit the values (in-order) representing the intersection + pub fn intersection<'a>(&'a self, other: &'a TreeMultiset) + -> IntersectionItems<'a, T, MultisetItems<'a, T>> { + IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Visit the values (in-order) representing the union + pub fn union<'a>(&'a self, other: &'a TreeMultiset) + -> UnionItems<'a, T, MultisetItems<'a, T>> { + UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} + } + + /// Return the number of occurrences of the value in the multiset. + #[inline] + pub fn count(&self, value: &T) -> uint { match self.map.find(value) { None => 0u, Some(count) => *count } } - fn is_disjoint(&self, other: &TreeMultiset) -> bool { + /// Return true if the multiset has no elements in common with `other`. + pub fn is_disjoint(&self, other: &TreeMultiset) -> bool { let mut x = self.iter(); let mut y = other.iter(); let mut a = x.next(); @@ -957,7 +1015,9 @@ impl Multiset for TreeMultiset { true } - fn is_subset(&self, other: &TreeMultiset) -> bool { + /// Return true if, for any given element, the number times it occurs in the + /// multiset is not greater than the number of times it occurs in `other`. + pub fn is_subset(&self, other: &TreeMultiset) -> bool { let mut x = self.iter(); let mut y = other.iter(); let mut a = x.next(); @@ -981,16 +1041,28 @@ impl Multiset for TreeMultiset { true } -} + /// Return true if the value occurs at least once in the multiset. + pub fn contains(&self, value: &T) -> bool { + self.count(value) > 0u + } + + /// Return true if the multiset is a superset of another. + pub fn is_superset(&self, other: &TreeMultiset) -> bool { + other.is_subset(self) + } -impl MutableMultiset for TreeMultiset { - fn insert_many(&mut self, value: T, n: uint) -> bool { + /// Add `n` occurrences of `value` to the multiset. Return true if the value + /// was not already present in the multiset. + pub fn insert_many(&mut self, value: T, n: uint) -> bool { let curr = self.count(&value); self.length += n; self.map.insert(value, curr + n) } - fn remove_many(&mut self, value: &T, n: uint) -> uint { + /// Remove `n` occurrences of `value` from the multiset. If there are less + /// than `n` occurrences, remove all occurrences. Return the number of + /// occurrences removed. + pub fn remove_many(&mut self, value: &T, n: uint) -> uint { let curr = self.count(value); if n >= curr { @@ -1008,63 +1080,27 @@ impl MutableMultiset for TreeMultiset { } } } -} - -impl Default for TreeMultiset { - #[inline] - fn default() -> TreeMultiset { TreeMultiset::new() } -} - -impl TreeMultiset { - /// Create an empty TreeMultiset - #[inline] - pub fn new() -> TreeMultiset { TreeMultiset {map: TreeMap::new(), length: 0} } - /// Get the number of distinct values in the multiset - pub fn num_distinct(&self) -> uint { self.map.len() } - - /// Get a lazy iterator over the values in the multiset. - /// Requires that it be frozen (immutable). - #[inline] - pub fn iter<'a>(&'a self) -> MultisetItems<'a, T> { - MultisetItems{iter: self.map.iter(), current: None, count: 0 } + /// Add one occurrence of `value` to the multiset. Return true if the value + /// was not already present in the multiset. + pub fn insert(&mut self, value: T) -> bool { + self.insert_many(value, 1) } - /// Get a lazy iterator over the values in the multiset. - /// Requires that it be frozen (immutable). - #[inline] - pub fn rev_iter<'a>(&'a self) -> RevMultisetItems<'a, T> { - RevMultisetItems{iter: self.map.rev_iter(), current: None, count: 0} - } - - /// Visit the values (in-order) representing the difference - pub fn difference<'a>(&'a self, other: &'a TreeMultiset) - -> DifferenceItems<'a, T, MultisetItems<'a, T>> { - DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visit the values (in-order) representing the symmetric difference - pub fn symmetric_difference<'a>(&'a self, other: &'a TreeMultiset) - -> SymDifferenceItems<'a, T, MultisetItems<'a, T>> { - SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visit the values (in-order) representing the multiset sum - pub fn sum<'a>(&'a self, other: &'a TreeMultiset) - -> SumItems<'a, T, MultisetItems<'a, T>> { - SumItems{a: self.iter().peekable(), b: other.iter().peekable()} - } - - /// Visit the values (in-order) representing the intersection - pub fn intersection<'a>(&'a self, other: &'a TreeMultiset) - -> IntersectionItems<'a, T, MultisetItems<'a, T>> { - IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} + /// Remove one occurrence of `value` from the multiset. Return true if the + /// value was present in the multiset. + pub fn remove(&mut self, value: &T) -> bool { + self.remove_many(value, 1) > 0u } +} - /// Visit the values (in-order) representing the union - pub fn union<'a>(&'a self, other: &'a TreeMultiset) - -> UnionItems<'a, T, MultisetItems<'a, T>> { - UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} +impl TreeMultiset { + pub fn to_set(&self) -> TreeSet { + let mut set = TreeSet::new(); + for (k, _) in self.map.clone().move_iter() { + set.insert(k); + } + set } } @@ -2204,7 +2240,7 @@ mod test_mset { use std::prelude::*; use std::hash; - use {Multiset, MutableMultiset, Mutable, MutableMap}; + use {Mutable, MutableMap}; use super::{TreeMap, TreeMultiset}; #[test] From dce9de81374ef06787143e1bce5d477351b28a11 Mon Sep 17 00:00:00 2001 From: nham Date: Tue, 22 Jul 2014 18:16:28 -0400 Subject: [PATCH 11/13] Implement lower_bound and upper_bound --- src/libcollections/treemap.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 3dd315ea93664..35a46cc37e9f7 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -957,6 +957,21 @@ impl TreeMultiset { RevMultisetItems{iter: self.map.rev_iter(), current: None, count: 0} } + /// Get a lazy iterator pointing to the first value greater than or equal to `v`. + /// If all elements in the multiset are less than `v`, an empty iterator is returned. + #[inline] + pub fn lower_bound<'a>(&'a self, v: &T) -> MultisetItems<'a, T> { + MultisetItems{iter: self.map.lower_bound(v), current: None, count: 0} + } + + /// Get a lazy iterator pointing to the first value greater than `v`. + /// If all elements in the multiset are not greater than `v`, an empty iterator + /// is returned. + #[inline] + pub fn upper_bound<'a>(&'a self, v: &T) -> MultisetItems<'a, T> { + MultisetItems{iter: self.map.upper_bound(v), current: None, count: 0} + } + /// Visit the values (in-order) representing the difference pub fn difference<'a>(&'a self, other: &'a TreeMultiset) -> DifferenceItems<'a, T, MultisetItems<'a, T>> { From 05aa1f3ef0b253d54d024d127c20dc56704b3b73 Mon Sep 17 00:00:00 2001 From: nham Date: Tue, 22 Jul 2014 19:01:07 -0400 Subject: [PATCH 12/13] Remove trailing whitespace, duplicate function definition. --- src/libcollections/treemap.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 35a46cc37e9f7..78ffdd20f1655 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -859,7 +859,7 @@ impl<'a, T: Ord, I: Iterator<&'a T>> Iterator<&'a T> for UnionItems<'a, T, I> { /// A implementation of a multiset on top of the `TreeMap` container. The only -/// requirement is that the type of the elements contained ascribes to the +/// requirement is that the type of the elements contained ascribes to the /// `Ord` trait. #[deriving(Clone)] pub struct TreeMultiset { @@ -1119,16 +1119,6 @@ impl TreeMultiset { } } -impl TreeMultiset { - pub fn to_set(&self) -> TreeSet { - let mut set = TreeSet::new(); - for (k, _) in self.map.clone().move_iter() { - set.insert(k); - } - set - } -} - /// Lazy forward iterator over a multiset pub struct MultisetItems<'a, T> { iter: Entries<'a, T, uint>, From 3af7a28e1dbee9f7168b30cde06ed727178033b7 Mon Sep 17 00:00:00 2001 From: nham Date: Thu, 31 Jul 2014 11:18:29 -0400 Subject: [PATCH 13/13] Inline a bunch of methods. Change one 0u -> 0 --- src/libcollections/treemap.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index 78ffdd20f1655..ecd99a4bc22e0 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -923,6 +923,7 @@ impl Extendable for TreeMultiset { } impl FromIterator for TreeMultiset { + #[inline] fn from_iter>(iter: Iter) -> TreeMultiset { let mut mset = TreeMultiset::new(); mset.extend(iter); @@ -941,6 +942,7 @@ impl TreeMultiset { pub fn new() -> TreeMultiset { TreeMultiset {map: TreeMap::new(), length: 0} } /// Get the number of distinct values in the multiset + #[inline] pub fn num_distinct(&self) -> uint { self.map.len() } /// Get a lazy iterator over the values in the multiset. @@ -973,30 +975,35 @@ impl TreeMultiset { } /// Visit the values (in-order) representing the difference + #[inline] pub fn difference<'a>(&'a self, other: &'a TreeMultiset) -> DifferenceItems<'a, T, MultisetItems<'a, T>> { DifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} } /// Visit the values (in-order) representing the symmetric difference + #[inline] pub fn symmetric_difference<'a>(&'a self, other: &'a TreeMultiset) -> SymDifferenceItems<'a, T, MultisetItems<'a, T>> { SymDifferenceItems{a: self.iter().peekable(), b: other.iter().peekable()} } /// Visit the values (in-order) representing the multiset sum + #[inline] pub fn sum<'a>(&'a self, other: &'a TreeMultiset) -> SumItems<'a, T, MultisetItems<'a, T>> { SumItems{a: self.iter().peekable(), b: other.iter().peekable()} } /// Visit the values (in-order) representing the intersection + #[inline] pub fn intersection<'a>(&'a self, other: &'a TreeMultiset) -> IntersectionItems<'a, T, MultisetItems<'a, T>> { IntersectionItems{a: self.iter().peekable(), b: other.iter().peekable()} } /// Visit the values (in-order) representing the union + #[inline] pub fn union<'a>(&'a self, other: &'a TreeMultiset) -> UnionItems<'a, T, MultisetItems<'a, T>> { UnionItems{a: self.iter().peekable(), b: other.iter().peekable()} @@ -1057,17 +1064,20 @@ impl TreeMultiset { } /// Return true if the value occurs at least once in the multiset. + #[inline] pub fn contains(&self, value: &T) -> bool { - self.count(value) > 0u + self.count(value) > 0 } /// Return true if the multiset is a superset of another. + #[inline] pub fn is_superset(&self, other: &TreeMultiset) -> bool { other.is_subset(self) } /// Add `n` occurrences of `value` to the multiset. Return true if the value /// was not already present in the multiset. + #[inline] pub fn insert_many(&mut self, value: T, n: uint) -> bool { let curr = self.count(&value); self.length += n; @@ -1077,6 +1087,7 @@ impl TreeMultiset { /// Remove `n` occurrences of `value` from the multiset. If there are less /// than `n` occurrences, remove all occurrences. Return the number of /// occurrences removed. + #[inline] pub fn remove_many(&mut self, value: &T, n: uint) -> uint { let curr = self.count(value); @@ -1098,12 +1109,14 @@ impl TreeMultiset { /// Add one occurrence of `value` to the multiset. Return true if the value /// was not already present in the multiset. + #[inline] pub fn insert(&mut self, value: T) -> bool { self.insert_many(value, 1) } /// Remove one occurrence of `value` from the multiset. Return true if the /// value was present in the multiset. + #[inline] pub fn remove(&mut self, value: &T) -> bool { self.remove_many(value, 1) > 0u }