use std::collections::HashMap;
use core::hash::Hash;
use core::cmp::Eq;
use core::fmt::Display;
use core::clone::Clone;
use core::fmt::LowerHex;
use std::fmt;
#[derive(Copy, Clone)]
pub struct Rle<T> {
pub part: T,
pub pos: usize,
pub cnt: usize,
pub max: bool
}
impl<T: Display + LowerHex> fmt::Debug for Rle<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<Rle@part:{:x},pos:{},cnt:{},max:{}>",
self.part, self.pos, self.cnt, self.max)
}
}
impl<T: PartialEq> PartialEq<Rle<T>> for Rle<T> {
fn eq(&self, other: &Rle<T>) -> bool {
return self.part.eq(&other.part) && self.pos == other.pos &&
self.cnt == other.cnt && self.max == other.max;
}
fn ne(&self, other: &Self) -> bool {
!self.eq(other)
}
}
struct Last<T: Eq + Hash + Display + Copy + Clone> {
pub val: Option<Rle<T>>,
pub max_poses: HashMap<T, Vec<usize>>,
pub ret: Vec<Rle<T>>
}
impl<T: Eq + Hash + Display + Copy + Clone + LowerHex> Last<T> {
pub fn handle_last(&mut self) {
if self.val.is_none() {
return;
}
let ref mut _last = self.val.as_mut().unwrap();
let max_rles = self.max_poses.entry(_last.part.clone()).or_insert(Vec::new());
for idx in max_rles.clone() {
let ref mut prev = self.ret[idx];
if prev.cnt > _last.cnt {
_last.max = false;
} else if prev.cnt == _last.cnt {
} else if prev.cnt < _last.cnt {
prev.max = false;
}
}
max_rles.push(self.ret.len());
_last.pos = self.ret.len();
self.ret.push(_last.clone());
}
}
#[allow(dead_code)]
pub fn code<T: Eq + Hash + Display + Copy + Clone + LowerHex>(parts: &Vec<T>) -> Vec<Rle<T>> {
let mut last = Last {
val: None,
max_poses: HashMap::new(),
ret: Vec::new()
};
for i in 0..parts.len() {
let ref part = parts[i];
if last.val.is_some() && last.val.unwrap().part == *part {
last.val.as_mut().unwrap().cnt += 1;
} else {
last.handle_last();
last.val = Some(Rle::<T>{ part: part.clone(), pos: 0, cnt: 1, max: true });
}
}
last.handle_last();
return last.ret;
}