use fxhash::FxHashMap;
use std::{hash::Hash, iter::repeat};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Counter<T: Hash + Eq> {
map: FxHashMap<T, isize>,
max: isize,
}
impl<T: Hash + Eq> Counter<T> {
pub fn new() -> Self {
Self::default()
}
pub const fn max(&self) -> isize {
self.max
}
pub fn increment(&mut self, value: T) -> isize {
*self
.map
.entry(value)
.and_modify(|count| {
*count += 1;
if *count > self.max {
self.max = *count;
}
})
.or_insert(1)
}
pub fn decrement(&mut self, value: T) -> isize {
*self
.map
.entry(value)
.and_modify(|count| {
if *count == self.max {
self.max -= 1;
}
*count -= 1;
})
.or_insert(-1)
}
}
impl<T: Eq + Hash> Default for Counter<T> {
fn default() -> Self {
Self {
map: FxHashMap::default(),
max: 0,
}
}
}
impl<T: Hash + Eq> FromIterator<T> for Counter<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut counter = Self::new();
iter.into_iter().for_each(|v| {
counter.increment(v);
});
counter
}
}
impl<T: Clone + Eq + Hash> From<Counter<T>> for Vec<T> {
fn from(value: Counter<T>) -> Self {
value
.map
.into_iter()
.flat_map(|(v, c)| repeat(v).take(c.try_into().unwrap_or(0)))
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_counter() {
let items = [3, 5, 9, 11, 14, 9, 9, 11];
let mut counter = Counter::new();
for item in items {
counter.increment(item);
}
assert_eq!(counter.max(), 3);
}
}