use std::fmt::{Display, Formatter, Result};
#[derive(Clone, Debug)]
pub struct Partition {
elems: Vec<usize>,
rev_elems: Vec<usize>,
set_id: Vec<usize>,
sets: Vec<Set>,
sieve: Vec<u64>,
touched: Vec<usize>,
}
#[derive(Clone, Debug, Copy)]
struct Set {
begin: usize,
end: usize,
mid: usize,
}
impl Set {
const fn len(&self) -> usize {
self.end - self.begin
}
}
impl Partition {
pub fn simple(size: usize) -> Self {
Self::with_singletons(size, 0)
}
pub fn with_singletons(size: usize, k: usize) -> Self {
assert!(k <= size);
let mut sets = Vec::with_capacity(size);
let num_parts = if k == size { k } else { k + 1 };
let mut set_id = if size > 0 {
vec![num_parts - 1; size]
} else {
Vec::new()
};
for (i, set_i) in set_id.iter_mut().enumerate().take(k) {
sets.push(Set {
begin: i,
mid: i,
end: i + 1,
});
*set_i = i
}
if size > k {
sets.push(Set {
begin: k,
mid: k,
end: size,
});
}
Self {
elems: (0..size).collect(),
rev_elems: (0..size).collect(),
set_id,
sets,
sieve: vec![0; size],
touched: Vec::with_capacity(size),
}
}
#[inline]
fn swap(&mut self, i1: usize, i2: usize) {
if i1 != i2 {
let e1 = self.elems[i1];
let e2 = self.elems[i2];
self.elems[i1] = e2;
self.elems[i2] = e1;
self.rev_elems[e1] = i2;
self.rev_elems[e2] = i1;
}
}
pub fn sieve(&mut self, e: usize, x: u64) {
if self.sieve[e] == 0 {
let set = &mut self.sets[self.set_id[e]];
if set.len() == 1 {
return;
};
if set.mid == set.begin {
self.touched.push(self.set_id[e]);
};
let new_pos = set.mid;
set.mid += 1;
self.swap(new_pos, self.rev_elems[e]);
}
self.sieve[e] += x;
}
pub fn split<F>(&mut self, mut callback: F)
where
F: FnMut(usize),
{
self.touched.sort();
for &s in &self.touched {
let set = self.sets[s];
let begin = set.begin;
let end = set.mid;
self.sets[s].mid = begin;
let sieve = &self.sieve;
self.elems[begin..end].sort_by_key(|e| sieve[*e]);
let mut current_set = s;
let mut current_key = self.sieve[self.elems[set.end - 1]];
for i in (begin..end).rev() {
let elem_i = self.elems[i];
if self.sieve[elem_i] != current_key {
current_key = self.sieve[elem_i];
self.sets[current_set].begin = i + 1;
self.sets[current_set].mid = i + 1;
self.sets.push(Set {
begin,
mid: begin,
end: i + 1,
});
current_set = self.num_parts() - 1;
callback(current_set);
}
self.set_id[elem_i] = current_set;
self.rev_elems[elem_i] = i;
self.sieve[elem_i] = 0;
}
}
self.touched.clear();
}
pub fn refine_by_value<F>(&mut self, key: &[u64], callback: F)
where
F: FnMut(usize),
{
for (i, &key) in key.iter().enumerate() {
self.sieve(i, key);
}
self.split(callback)
}
fn parent_set(&self, s: usize) -> usize {
self.set_id[self.elems[self.sets[s].end]]
}
pub fn undo(&mut self, nparts: usize) {
for s in (nparts..self.num_parts()).rev() {
let set = self.sets[s];
let parent = self.parent_set(s);
for e in &mut self.elems[set.begin..set.end] {
self.set_id[*e] = parent
}
self.sets[parent].begin = set.begin;
self.sets[parent].mid = set.begin;
}
self.sets.truncate(nparts);
}
#[inline]
pub fn part(&self, part: usize) -> &[usize] {
&self.elems[self.sets[part].begin..self.sets[part].end]
}
#[inline]
pub fn num_parts(&self) -> usize {
self.sets.len()
}
pub fn num_elems(&self) -> usize {
self.elems.len()
}
#[inline]
pub fn is_discrete(&self) -> bool {
self.elems.len() == self.sets.len()
}
pub fn individualize(&mut self, e: usize) -> Option<usize> {
let s = self.set_id[e];
if self.sets[s].end - self.sets[s].begin >= 2 {
let i = self.rev_elems[e];
self.swap(i, self.sets[s].begin);
let delimiter = self.sets[s].begin + 1;
let new_set = self.num_parts();
self.set_id[e] = new_set;
let new_begin = self.sets[s].begin;
self.sets.push(Set {
begin: new_begin,
mid: new_begin,
end: delimiter,
});
self.sets[s].begin = delimiter;
self.sets[s].mid = delimiter;
Some(new_set)
} else {
None
}
}
pub fn as_bijection(&self) -> Option<&[usize]> {
if self.is_discrete() {
Some(&self.rev_elems)
} else {
None
}
}
pub const fn parts(&self) -> PartsIterator<'_> {
PartsIterator {
partition: self,
pos: 0,
}
}
fn check_consistent(&self) {
let n = self.elems.len();
assert_eq!(self.rev_elems.len(), n);
for i in 0..n {
assert_eq!(self.rev_elems[self.elems[i]], i);
assert_eq!(self.elems[self.rev_elems[i]], i);
}
for (i, set) in self.sets.iter().enumerate() {
assert!(set.begin < set.end);
assert!(set.begin <= set.mid);
assert!(set.mid <= set.end);
for j in set.begin..set.end {
assert_eq!(self.set_id[self.elems[j]], i)
}
for j in set.begin..set.mid {
assert!(self.sieve[j] != 0)
}
for j in set.mid..set.end {
assert_eq!(self.sieve[j], 0)
}
}
}
}
pub struct PartsIterator<'a> {
partition: &'a Partition,
pos: usize,
}
impl<'a> Iterator for PartsIterator<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
if let Some(&e) = self.partition.elems.get(self.pos) {
let s = self.partition.set_id[e];
self.pos = self.partition.sets[s].end;
Some(s)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let n_parts = self.partition.num_parts();
let lower = if self.pos < n_parts {
n_parts - self.pos
} else {
0
};
(lower, Some(n_parts))
}
}
impl Display for Partition {
fn fmt(&self, f: &mut Formatter) -> Result {
self.check_consistent();
write!(f, "(")?;
for i in 0..self.elems.len() {
if i > 0 {
if self.sets[self.set_id[self.elems[i]]].begin == i {
write!(f, ")(")?;
} else {
write!(f, ",")?;
}
}
write!(f, "{}", self.elems[i])?;
}
write!(f, ")")?;
Ok(())
}
}