#![warn(
clippy::all,
clippy::pedantic,
clippy::nursery,
clippy::cargo,
)]
use crate::birthdeath::BirthDeath;
use std::collections::{BinaryHeap, VecDeque};
#[derive(Debug, Clone)]
enum EventType {
Birth,
Death,
}
#[derive(Debug, Clone)]
struct Node {
birth_event: Event,
death_event: Event,
id: usize,
alive: bool,
in_top_k: bool,
is_dead: bool,
}
const fn get_value(n: &Node) -> &Event {
if n.alive {
&n.death_event
} else {
&n.birth_event
}
}
impl Ord for Node {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let me = get_value(self).value;
let oth = get_value(other).value;
if me < oth {
return std::cmp::Ordering::Greater;
}
if oth < me {
return std::cmp::Ordering::Less;
}
std::cmp::Ordering::Equal
}
}
impl PartialOrd for Node {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for Node {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl Eq for Node {}
#[derive(Debug, Clone)]
struct Event {
event_type: EventType,
value: f64,
}
const fn create_event(birth: f64, death: f64, i: usize) -> Node {
Node {
birth_event: Event {
event_type: EventType::Birth,
value: birth,
},
death_event: Event {
event_type: EventType::Death,
value: death,
},
id: i,
alive: false,
in_top_k: false,
is_dead: false,
}
}
fn generate_events(bd_pairs: Vec<BirthDeath>) -> Vec<Node> {
bd_pairs
.into_iter()
.filter(|BirthDeath { birth, death }| death.is_finite() && birth.is_finite())
.enumerate()
.map(|(i, BirthDeath { birth, death })| create_event(birth, death, i))
.collect::<Vec<_>>()
}
const fn node_to_birthdeath(n: &Node) -> BirthDeath {
BirthDeath {
birth: n.birth_event.value,
death: n.death_event.value,
}
}
#[must_use]
pub fn filter(bd_pairs: Vec<BirthDeath>, k: usize) -> Vec<BirthDeath> {
let mut nodes = generate_events(bd_pairs);
let mut event_stack = BinaryHeap::from(nodes.clone());
let sweep_status: &mut VecDeque<usize> = &mut VecDeque::new();
let mut filtered_output: Vec<BirthDeath> = Vec::new();
let mut in_top = 0;
let mut waiting = 0;
while let Some(mut event) = event_stack.pop(){
match get_value(&event).event_type {
EventType::Birth => {
if in_top < k {
in_top += 1;
filtered_output.push(node_to_birthdeath(&event));
nodes[event.id].in_top_k = true;
}
nodes[event.id].alive = true;
event.alive = true;
sweep_status.push_back(event.id);
event_stack.push(event);
}
EventType::Death => {
nodes[event.id].is_dead = true;
if nodes[event.id].in_top_k {
waiting += 1;
}
if waiting > 0 {
let mut front_index = sweep_status.get(0);
while front_index.is_some() && nodes[*front_index.unwrap()].is_dead {
sweep_status.pop_front();
front_index = sweep_status.get(0);
}
if front_index.is_none() {
continue;
}
let front = *front_index.unwrap();
if !nodes[front].in_top_k {
nodes[front].in_top_k = true;
filtered_output.push(node_to_birthdeath(&nodes[front]));
}
}
}
}
}
filtered_output
}