#![warn(missing_docs)]
use std::borrow::{Borrow};
use std::collections::{HashMap};
use std::collections::hash_map;
use std::collections::hash_map::{Entry,Keys};
use std::hash::{Hash};
use std::iter::{FromIterator,IntoIterator};
use std::ops::{Add, Sub};
use std::fmt;
#[derive(Clone)]
pub struct HashMultiSet<K>
{
elem_counts: HashMap<K, usize>,
size: usize,
}
pub struct Iter<'a, K: 'a> {
iter: hash_map::Iter<'a, K, usize>,
duplicate: Option<(&'a K, &'a usize)>,
duplicate_index: usize,
}
impl<'a, K> Clone for Iter<'a, K> {
fn clone(&self) -> Iter<'a, K> {
Iter {
iter: self.iter.clone(),
duplicate: self.duplicate.clone(),
duplicate_index: self.duplicate_index,
}
}
}
impl<'a, K> Iterator for Iter<'a, K> {
type Item = &'a K;
fn next(&mut self) -> Option<&'a K> {
if self.duplicate.is_none() {
self.duplicate = self.iter.next();
}
if self.duplicate.is_some() {
let (key, count) = self.duplicate.unwrap();
self.duplicate_index += 1;
if &self.duplicate_index >= count {
self.duplicate = None;
self.duplicate_index = 0;
}
Some(key)
} else {
None
}
}
}
impl<K> HashMultiSet<K> where
K: Eq + Hash
{
pub fn new() -> Self {
HashMultiSet {
elem_counts: HashMap::new(),
size: 0,
}
}
pub fn iter(&self) -> Iter<K> {
Iter {
iter: self.elem_counts.iter(),
duplicate: None,
duplicate_index: 0,
}
}
pub fn is_empty(&self) -> bool {
self.elem_counts.is_empty()
}
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
where K: Borrow<Q>,
Q: Hash + Eq
{
self.elem_counts.contains_key(value)
}
pub fn len(&self) -> usize {
self.size
}
pub fn distinct_elements<'a>(&'a self) -> Keys<'a, K, usize> {
self.elem_counts
.keys()
}
pub fn insert(&mut self, val: K) {
self.insert_times(val, 1);
}
pub fn insert_times(&mut self, val: K, n: usize) {
self.size += n;
match self.elem_counts.entry(val) {
Entry::Vacant(view) => {
view.insert(n);
},
Entry::Occupied(mut view) => {
let v = view.get_mut();
*v += n;
},
}
}
pub fn remove(&mut self, val: &K) -> bool {
self.remove_times(val, 1) > 0
}
pub fn remove_times(&mut self, val: &K, times: usize) -> usize {
{
let entry = self.elem_counts.get_mut(val);
if entry.is_some() {
let count = entry.unwrap();
if *count > times {
*count -= times;
self.size -= times;
return times
}
self.size -= *count;
}
}
self.elem_counts.remove(val).unwrap_or(0)
}
pub fn remove_all(&mut self, val: &K) {
self.elem_counts.remove(val);
}
pub fn count_of(&self, val: &K) -> usize {
self.elem_counts
.get(val)
.map_or(0, |x| *x)
}
}
impl<T> Add for HashMultiSet<T> where
T: Eq + Hash + Clone
{
type Output = HashMultiSet<T>;
fn add(self, rhs: HashMultiSet<T>) -> HashMultiSet<T> {
let mut ret: HashMultiSet<T> = HashMultiSet::new();
for val in self.distinct_elements() {
let count = self.count_of(val);
ret.insert_times((*val).clone(), count);
}
for val in rhs.distinct_elements() {
let count = rhs.count_of(val);
ret.insert_times((*val).clone(), count);
}
ret
}
}
impl<T> Sub for HashMultiSet<T> where
T: Eq + Hash + Clone
{
type Output = HashMultiSet<T>;
fn sub(self, rhs: HashMultiSet<T>) -> HashMultiSet<T> {
let mut ret = self.clone();
for val in rhs.distinct_elements() {
let count = rhs.count_of(val);
ret.remove_times(val, count);
}
ret
}
}
impl<A> FromIterator<A> for HashMultiSet<A> where
A: Eq + Hash
{
fn from_iter<T>(iterable: T) -> HashMultiSet<A> where
T: IntoIterator<Item=A>
{
let mut multiset: HashMultiSet<A> = HashMultiSet::new();
for elem in iterable.into_iter() {
multiset.insert(elem);
}
multiset
}
}
impl<T> PartialEq for HashMultiSet<T>
where
T: Eq + Hash,
{
fn eq(&self, other: &HashMultiSet<T>) -> bool {
if self.len() != other.len() {
return false;
}
self.elem_counts.iter().all(|(key, count)| {
other.contains(key) && other.elem_counts.get(key).unwrap() == count
})
}
}
impl<T> Eq for HashMultiSet<T>
where
T: Eq + Hash,
{
}
impl<T> fmt::Debug for HashMultiSet<T>
where
T: Eq + Hash + fmt::Debug
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
#[cfg(test)]
mod test_multiset {
use super::HashMultiSet;
#[test]
fn test_iterate() {
let mut a = HashMultiSet::new();
for i in 0..16 {
a.insert(i);
}
for i in 0..8 {
a.insert(i);
}
for i in 0..4 {
a.insert(i);
}
let mut observed: u16 = 0;
let mut observed_twice: u16 = 0;
let mut observed_thrice: u16 = 0;
for k in a.iter() {
let bit = 1 << *k;
if observed & bit == 0 {
observed |= bit;
} else if observed_twice & bit == 0 {
observed_twice |= bit;
} else if observed_thrice & bit == 0 {
observed_thrice |= bit;
}
}
assert_eq!(observed, 0xFFFF);
assert_eq!(observed_twice, 0xFF);
assert_eq!(observed_thrice, 0xF);
}
#[test]
fn test_eq() {
let mut s1 = HashMultiSet::new();
s1.insert(0);
s1.insert(1);
s1.insert(1);
let mut s2 = HashMultiSet::new();
s2.insert(0);
s2.insert(1);
assert!(s1 != s2);
s2.insert(1);
assert_eq!(s1, s2);
}
}