use std::cmp::max;
use std::fmt::{Debug, Formatter, Result};
pub(super) struct LimitHeap {
pub(super) inner: [i32; 255],
pub(super) original: i32,
pub(super) current: usize,
}
impl Default for LimitHeap {
fn default() -> Self {
Self {
inner: [0; 255],
original: 0,
current: 0,
}
}
}
impl Debug for LimitHeap {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let msg = format!(
"LimitHeap {{ original: {}, current: {}, inner: [{}...] }}",
self.original, self.current, self.inner[0]
);
write!(f, "{msg}")
}
}
impl LimitHeap {
pub(super) fn move_right(&mut self) -> usize {
if self.has_children() {
let tmp = self.current;
let new_index = self.current * 2 + 2;
if new_index < self.inner.len() {
self.current = new_index;
} else {
log::warn!(
"Heap navigation out of bounds: move_right from {} would go to {}",
tmp,
new_index
);
}
return tmp;
}
self.current
}
pub(super) fn move_left(&mut self) -> usize {
if self.has_children() {
let tmp = self.current;
let new_index = self.current * 2 + 1;
if new_index < self.inner.len() {
self.current = new_index;
} else {
log::warn!(
"Heap navigation out of bounds: move_left from {} would go to {}",
tmp,
new_index
);
}
return tmp;
}
self.current
}
pub(super) fn move_up(&mut self) -> usize {
if self.has_parent() {
let tmp = self.current;
self.current = (self.current - 1) / 2;
return tmp;
}
self.current
}
pub(super) fn move_to(&mut self, index: usize) {
if index < self.inner.len() {
self.current = index;
} else {
log::warn!(
"Heap navigation out of bounds: move_to({}) exceeds array length {}",
index,
self.inner.len()
);
}
}
pub(super) fn value(&self) -> i32 {
if self.current < self.inner.len() {
self.inner[self.current]
} else {
log::error!(
"Heap index out of bounds in value(): current={}, len={}",
self.current,
self.inner.len()
);
0 }
}
pub(super) fn set_value(&mut self, value: i32) {
if self.current < self.inner.len() {
self.inner[self.current] = value;
} else {
log::error!(
"Heap index out of bounds in set_value(): current={}, len={}",
self.current,
self.inner.len()
);
}
}
pub(super) fn has_parent(&self) -> bool {
self.current > 0
}
pub(super) fn parent_value(&mut self) -> i32 {
if self.has_parent() {
let current = self.move_up();
let val = self.value();
self.move_to(current);
return val;
}
self.original
}
pub(super) fn has_children(&self) -> bool {
self.current * 2 + 2 <= self.inner.len()
}
fn right_child_value(&mut self) -> i32 {
let tmp = self.move_right();
let val = self.value();
self.move_to(tmp);
val
}
fn set_left_child(&mut self) {
let parent = self.parent_value();
let current = self.value();
let value = ((parent - current).abs() / 2) + current;
self.move_left();
self.set_value(value);
self.move_up();
}
fn set_right_child(&mut self) {
let parent = self.parent_value();
let current = self.value();
let value = current - ((parent - current).abs() / 2);
self.move_right();
self.set_value(value);
self.move_up();
}
pub(super) fn clamp_to_max(&mut self, max: i32) {
for i in 0..self.inner.len() {
if self.inner[i] > 0 && self.inner[i] > max {
self.inner[i] = max;
}
}
}
pub(super) fn build(&mut self) {
let original = max(self.original, 2);
let root = original / 2;
self.inner[0] = root; self.inner[1] = ((original - root).abs() / 2) + root;
self.inner[2] = root - ((original - root).abs() / 2);
for i in 1..self.inner.len() {
self.move_to(i);
if self.has_children() && self.right_child_value() == 0 {
self.set_left_child();
self.set_right_child();
}
}
self.move_to(0); }
}