#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(unused_parens)]
#![allow(unused_mut)]
#![allow(unused_assignments)]
#![allow(unused_doc_comments)]
#![allow(unused_imports)]
use core::cell::{Ref, RefCell, RefMut};
use core::cmp::Ord;
use core::fmt::{Display,Debug};
use std::collections::hash_map::RandomState;
use core::hash::{BuildHasher, Hash, Hasher};
fn left(i:usize) -> usize { 2*i+1 }
fn right(i:usize) -> usize { 2*i+2 }
fn parent(i:usize) -> usize { (i-1)/2 }
fn optcmp<VT:PartialOrd>(a:&Option<(VT,usize)>, b:&Option<(VT,usize)>, neg:bool) -> bool
{
match (a,b,neg) {
(Some((av,_)), Some((bv,_)),true) => av < bv,
(Some((av,_)), Some((bv,_)),false) => bv < av,
_ => false,
}
}
#[derive(Clone, Debug)]
pub struct ConstHashHeap<KT,VT, const CAPACITY:usize = 1024>
{
keys : [Option<(KT,usize)>;CAPACITY],
vals : [Option<(VT,usize)>;CAPACITY],
maxhashes : [usize;CAPACITY], size : usize,
autostate: RandomState,
lessthan : fn(&Option<(VT,usize)>,&Option<(VT,usize)>) -> bool,
}
impl<KT:Hash+Eq, VT:PartialOrd, const CAP:usize> ConstHashHeap<KT,VT,CAP> {
pub fn new(maxheap:bool) -> Self {
ConstHashHeap {
keys : [const { None }; CAP],
vals : [const { None }; CAP], maxhashes : [0;CAP],
size : 0,
autostate : RandomState::new(),
lessthan : if maxheap{|a,b|optcmp(a,b,true)} else {|a,b|optcmp(a,b,false)},
}
}
fn hash(&self,key:&KT) -> usize {
let mut bs = self.autostate.build_hasher(); key.hash(&mut bs);
(bs.finish() as usize) % CAP
}
fn rehash(h:usize) -> usize { (h+1) % CAP }
fn borrow_hash(&self, key:&KT, rs:&RandomState) -> usize {
let mut bs = rs.build_hasher();
key.hash(&mut bs);
(bs.finish() as usize) % CAP
}
fn swap(&mut self, i:usize, k:usize) {
self.vals.swap(i,k);
if let Some((ival,ik)) = &mut self.vals[i] {
self.keys[*ik].as_mut().map(|pair|pair.1 = i);
}
if let Some((kval,kk)) = &mut self.vals[k] {
self.keys[*kk].as_mut().map(|pair|{pair.1 = k;});
}
}
fn swapup(&mut self, mut i:usize) -> usize {
let mut pi = if (i>0) {parent(i)} else {0};
while (i>0 && (self.lessthan)(&self.vals[pi],&self.vals[i])) {
self.swap(i,pi);
i = pi;
if (i>0) {pi = parent(i)};
}
i
}
fn swapdown(&mut self, mut i:usize) -> usize {
let mut si = Some(0);
while si.is_some() {
si = None;
let lf = left(i);
let rt = right(i);
if (lf<self.size && (self.lessthan)(&self.vals[i],&self.vals[lf])) {
si = Some(lf);
}
if(rt<self.size && (self.lessthan)(&self.vals[i],&self.vals[rt])
&& (self.lessthan)(&self.vals[lf],&self.vals[rt])) {
si = Some(rt);
}
if let Some(k) = si {
self.swap(i,k);
i = k;
}
} i
}
fn adjust(&mut self, i:usize, both:bool) -> usize {
let k = self.swapup(i);
if k==i && both {self.swapdown(i)} else {k}
}
pub fn size(&self) -> usize {self.size}
pub fn insert(&mut self, key:KT, val:VT) -> bool
{
let h0 = self.hash(&key);
let mut h = h0;
let mut hashes = 1;
let mut target_index = -1;
let mut keyfoundloc = None;
loop {
match &self.keys[h] {
Some((k,vi)) if k==&key => {
keyfoundloc = Some(*vi);
break;
},
Some(_) => { h = Self::rehash(h); hashes+=1; },
None if hashes < self.maxhashes[h0] => {
if target_index == -1 { target_index = h as isize; }
h=Self::rehash(h);
hashes += 1;
},
None => {
keyfoundloc = Some(self.size);
break;
},
} } match &keyfoundloc { Some(vi) if *vi==self.size && self.size >= CAP => {
return false;
}
Some(vi) if *vi == self.size => {
self.size+=1;
if target_index>=0 {h = target_index as usize;}
},
_ => {},
} if hashes > self.maxhashes[h0] {
self.maxhashes[h0] = hashes;
}
if let Some(vi) = keyfoundloc {
self.keys[h] = Some((key,vi));
self.vals[vi] = Some((val,h));
self.adjust(vi, vi+1<self.size);
}
true
}
fn find_and<F>(&mut self, key:KT, modifier:F)
-> (Option<VT>, Option<usize>) where F: FnOnce(Option<&VT>) -> VT
{
let mut valpos = None; let h0 = self.hash(&key);
let mut h = h0;
let mut hashes = 1;
let mut reuse_index = -1;
loop {
match &self.keys[h] {
Some((k,vi)) if k==&key => {
valpos = Some(*vi);
break;
},
Some(_) => { h = Self::rehash(h); hashes+=1; },
None if hashes < self.maxhashes[h0] => {
if reuse_index == -1 { reuse_index = h as isize; }
h=Self::rehash(h);
hashes += 1;
},
None => {
valpos = Some(self.size);
break;
},
} } match &valpos { Some(vi) if *vi==self.size && self.size >= CAP => {
return (None, None);
}
Some(vi) if *vi == self.size => {
self.size+=1;
if reuse_index>=0 {h = reuse_index as usize;}
},
_ => {},
} if hashes > self.maxhashes[h0] {
self.maxhashes[h0] = hashes;
}
let mut swaptmp = None;
if let Some(vi) = valpos {
self.keys[h] = Some((key,vi));
std::mem::swap(&mut self.vals[vi], &mut swaptmp);
self.vals[vi] = Some((modifier(swaptmp.as_ref().map(|(v,_)|v)), h));
self.adjust(vi, vi+1<self.size);
}
(swaptmp.map(|p|p.0), Some(h))
}
pub fn and_generate<F>(&mut self, key:KT, generator:F) -> Option<usize>
where F: FnOnce(Option<&VT>) -> VT
{ self.find_and(key,generator).1
}
pub fn set_at(&mut self, key:KT, val:VT) -> Option<usize>
{
self.find_and(key, |_|val).1
}
pub fn push(&mut self, key:KT, val:VT) -> bool { self.insert(key,val)
}
pub fn get(&self, key:&KT) -> Option<&VT> {
self.getopt(None,key)
}
pub fn get_at(&self, index:usize, key:&KT) -> Option<&VT> {
self.getopt(Some(index), key)
}
fn getopt(&self, iopt:Option<usize>, key:&KT) -> Option<&VT> {
let mut answer = None;
match iopt {
Some(h) if h<self.keys.len() => {
match &self.keys[h] {
Some((k,vi)) if k==key => {
return self.vals[*vi].as_ref().map(|p|&p.0);
},
_ => {},
} },
_ => {},
} let h0 = self.hash(&key);
let mut h = h0;
let mut hashes = 1;
loop {
match &self.keys[h] {
Some((k,vi)) if k==key => {
answer = self.vals[*vi].as_ref().map(|p|&p.0);
break;
},
_ if hashes < self.maxhashes[h0] => {
h=Self::rehash(h);
hashes += 1;
}
_ => { break; }
} } answer
}
pub fn modify<F:FnOnce(&mut VT)>(&mut self, key:&KT, f:F) -> bool {
self.modify_opt(None,key,f).is_some()
}
pub fn modify_at<F>(&mut self, index:usize, key:&KT, f:F) -> Option<usize>
where F:FnOnce(&mut VT)
{
self.modify_opt(Some(index),key,f)
}
fn modify_opt<F>(&mut self, iopt:Option<usize>, key:&KT, f:F) -> Option<usize>
where F:FnOnce(&mut VT)
{
match iopt {
Some(h) if h < self.keys.len() => {
match &self.keys[h] {
Some((k,vi)) if k==key => {
self.vals[*vi].as_mut().map(|p|f(&mut p.0));
self.adjust(*vi, vi+1<self.size);
return Some(h);
},
_ => {},
} },
_ => {},
} let h0 = self.hash(&key);
let mut h = h0;
let mut hashes = 1;
let mut valpos = None;
loop {
match &self.keys[h] {
Some((k,vi)) if k==key => {
valpos = Some(*vi);
break;
},
_ if hashes < self.maxhashes[h0] => {
h=Self::rehash(h);
hashes += 1;
}
_ => { break; }
} } if let Some(vi) = valpos {
self.vals[vi].as_mut().map(|p|f(&mut p.0));
self.adjust(vi, vi+1<self.size);
Some(h)
}
else {None}
}
pub fn remove(&mut self, key:&KT) -> Option<(KT,VT)> {
self.remove_opt(None,key)
}
pub fn remove_at(&mut self, index:usize, key:&KT) -> Option<(KT,VT)> {
self.remove_opt(Some(index),key)
}
fn remove_opt(&mut self, iopt:Option<usize>, key:&KT) -> Option<(KT,VT)> {
let mut answer = None;
let mut valpos = None;
let mut h = 0; match iopt {
Some(idx) if idx < self.keys.len() => {
match &self.keys[idx] {
Some((k,vi)) if k==key => {
valpos = Some(*vi);
h = idx;
},
_ => {},
} }
_ => {},
} if valpos.is_none() {
let h0 = self.hash(&key);
h = h0;
let mut hashes = 1;
loop {
match &self.keys[h] {
Some((k,vi)) if k==key => {
valpos = Some(*vi);
break;
},
_ if hashes < self.maxhashes[h0] => {
h=Self::rehash(h);
hashes += 1;
}
_ => { break; }
} } }
if let Some(vi) = valpos {
let mut ak = None;
let mut av = None;
core::mem::swap(&mut ak, &mut self.keys[h]);
core::mem::swap(&mut av, &mut self.vals[vi]);
answer = ak.zip(av).map(|(a,b)|(a.0,b.0));
if (vi+1 != self.size) {
self.swap(vi,self.size-1);
self.adjust(vi,true);
}
self.size -= 1;
}
answer
}
pub fn pop(&mut self) -> Option<(KT,VT)> {
let mut answer = None;
if self.size < 1 { return answer; }
if let Some((_,ki)) = &self.vals[0] {
let mut ak = None;
let mut av = None;
core::mem::swap(&mut ak, &mut self.keys[*ki]);
core::mem::swap(&mut av, &mut self.vals[0]);
answer = ak.zip(av).map(|(a,b)|(a.0,b.0));
self.size -= 1;
if (self.size>0) {
self.swap(0,self.size);
self.swapdown(0);
}
}
answer
}
pub fn peek(&self) -> Option<(&KT,&VT)> {
if self.size < 1 { None }
else {
self.vals[0].as_ref().and_then(|vp|
self.keys[vp.1].as_ref().map(|kp|(&kp.0,&vp.0)))
}
}
pub fn load_factor(&self) -> f32 {
(self.size as f32) / (CAP as f32)
}
pub fn resize<const NEWCAP:usize>(mut self) -> ConstHashHeap<KT,VT,NEWCAP> {
let mut hp2 = ConstHashHeap::new(true);
hp2.lessthan = self.lessthan;
hp2.size = self.size;
for i in 0..self.size {
let mut h = 0;
if let Some((_,ki)) = &self.vals[i] {
self.keys[*ki].as_ref().map(|(key,vi)|{
let h0 = hp2.borrow_hash(key,&self.autostate);
h = h0;
let mut hashes = 1;
loop {
match hp2.keys[h] {
Some(_) => {
h = (h+1) % NEWCAP;
hashes += 1;
},
None => {
break;
},
} } hp2.maxhashes[h0] = hashes;
});
core::mem::swap(&mut hp2.keys[h],&mut self.keys[*ki]);
self.vals[i].as_mut().map(|p|{p.1 = h;});
} core::mem::swap(&mut hp2.vals[i], &mut self.vals[i]);
} hp2.autostate = self.autostate;
hp2
}
pub fn refresh(mut self) -> Self {
self.resize()
}
pub fn iter<'a>(&'a self) -> CHHIter<'a,KT,VT,CAP> {
CHHIter {
chh : self,
index : 0,
}
}
pub fn priority_stream<'a>(&'a mut self) -> PriorityStream<'a,KT,VT,CAP> {
PriorityStream(self)
}
}
impl<KT: Hash + Eq, VT: PartialOrd, const CAP:usize> core::ops::Index<&KT>
for ConstHashHeap<KT,VT,CAP>
{
type Output = VT;
fn index(&self, index: &KT) -> &Self::Output {
self.get(index).expect("key not found")
}
}
impl<KT:Display+Debug+Hash+Eq, VT:Display+Debug+PartialOrd, const CAP:usize> ConstHashHeap<KT,VT,CAP>
{
pub fn diagnostics(&self, print:bool) -> f32 {
let mut mx = 0;
let mut hashes = 0;
for i in 0..CAP {
if self.maxhashes[i] > 0 {
mx += 1;
hashes += self.maxhashes[i];
}
}
let ave_hashes = if mx==0 {0.0} else {(hashes as f32) / (mx as f32)};
if print {
println!("--- table ---");
for i in 0..CAP {
println!("{i}: {:?}, \t {:?} \t hash {} maxhs {}",&self.keys[i],&self.vals[i],
self.keys[i].as_ref().map(|p|self.hash(&p.0).to_string()).unwrap_or(String::new()),self.maxhashes[i]);
}
println!("--table size {}, capacity {}, average number of hash/rehashes: {}--", self.size, CAP, ave_hashes);
} ave_hashes
}}
pub struct CHHIter<'a, KT,VT, const CAP:usize>
{
chh : &'a ConstHashHeap<KT,VT,CAP>,
index : usize,
}impl<'a,KT: Hash + Eq, VT: PartialOrd, const CAP:usize>
Iterator for CHHIter<'a,KT,VT,CAP> {
type Item = (&'a KT, &'a VT);
fn next(&mut self) -> Option<Self::Item> {
let mut answer = None;
if self.index >= self.chh.size() {return answer;}
self.index+=1;
if let Some((val,ki)) = &self.chh.vals[self.index-1] {
if let Some((key,vi)) = &self.chh.keys[*ki] {
answer = Some((key,val));
}
}
answer
}}
impl<'a, KT: Hash + Eq, VT: PartialOrd, const CAP:usize> IntoIterator
for &'a ConstHashHeap<KT,VT,CAP>
{
type Item = (&'a KT, &'a VT);
type IntoIter = CHHIter<'a,KT,VT,CAP>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
pub struct PriorityStream<'a,KT,VT,const CAP:usize>(&'a mut ConstHashHeap<KT,VT,CAP>);
impl<'a,KT: Hash + Eq, VT: PartialOrd, const CAP:usize> Iterator
for PriorityStream<'a,KT,VT,CAP>
{
type Item = (KT,VT);
fn next(&mut self) -> Option<Self::Item> {
self.0.pop()
}
}
impl<'a, KT: Hash + Eq, VT: PartialOrd, const CAP:usize> IntoIterator
for &'a mut ConstHashHeap<KT,VT,CAP>
{
type Item = (KT,VT);
type IntoIter = PriorityStream<'a,KT,VT,CAP>;
fn into_iter(self) -> Self::IntoIter {
PriorityStream(self)
}
}