use super::functions::*;
#[allow(dead_code)]
pub struct FixpointIterator<T: Ord + Clone + Eq> {
current: T,
bottom: T,
max_iters: usize,
}
impl<T: Ord + Clone + Eq> FixpointIterator<T> {
pub fn new(bottom: T, max_iters: usize) -> Self {
Self {
current: bottom.clone(),
bottom,
max_iters,
}
}
pub fn compute<F: Fn(&T) -> T>(&mut self, f: &F) -> Option<T> {
self.current = self.bottom.clone();
for _ in 0..self.max_iters {
let next = f(&self.current);
if next == self.current {
return Some(self.current.clone());
}
self.current = next;
}
None
}
pub fn current(&self) -> &T {
&self.current
}
pub fn reset(&mut self) {
self.current = self.bottom.clone();
}
}
#[allow(dead_code)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BoundedRange<T: Ord + Clone> {
lo: T,
hi: T,
}
impl<T: Ord + Clone> BoundedRange<T> {
pub fn new(lo: T, hi: T) -> Self {
assert!(lo <= hi, "BoundedRange: lo must be <= hi");
Self { lo, hi }
}
pub fn try_new(lo: T, hi: T) -> Option<Self> {
if lo <= hi {
Some(Self { lo, hi })
} else {
None
}
}
pub fn contains(&self, val: &T) -> bool {
val >= &self.lo && val <= &self.hi
}
pub fn lo(&self) -> &T {
&self.lo
}
pub fn hi(&self) -> &T {
&self.hi
}
pub fn clamp(&self, val: T) -> T {
if val < self.lo {
self.lo.clone()
} else if val > self.hi {
self.hi.clone()
} else {
val
}
}
pub fn intersect(&self, other: &Self) -> Option<Self> {
let lo = if self.lo >= other.lo {
self.lo.clone()
} else {
other.lo.clone()
};
let hi = if self.hi <= other.hi {
self.hi.clone()
} else {
other.hi.clone()
};
Self::try_new(lo, hi)
}
pub fn overlaps(&self, other: &Self) -> bool {
self.lo <= other.hi && other.lo <= self.hi
}
pub fn includes(&self, other: &Self) -> bool {
self.lo <= other.lo && other.hi <= self.hi
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum OrdResult {
Less,
Equal,
Greater,
}
impl OrdResult {
pub fn swap(self) -> Self {
match self {
OrdResult::Less => OrdResult::Greater,
OrdResult::Equal => OrdResult::Equal,
OrdResult::Greater => OrdResult::Less,
}
}
pub fn then(self, other: OrdResult) -> Self {
match self {
OrdResult::Equal => other,
_ => self,
}
}
pub fn is_lt(self) -> bool {
self == OrdResult::Less
}
pub fn is_eq(self) -> bool {
self == OrdResult::Equal
}
pub fn is_gt(self) -> bool {
self == OrdResult::Greater
}
pub fn is_le(self) -> bool {
self != OrdResult::Greater
}
pub fn is_ge(self) -> bool {
self != OrdResult::Less
}
pub fn to_signum(self) -> i32 {
match self {
OrdResult::Less => -1,
OrdResult::Equal => 0,
OrdResult::Greater => 1,
}
}
pub fn from_std(o: std::cmp::Ordering) -> Self {
match o {
std::cmp::Ordering::Less => OrdResult::Less,
std::cmp::Ordering::Equal => OrdResult::Equal,
std::cmp::Ordering::Greater => OrdResult::Greater,
}
}
pub fn to_std(self) -> std::cmp::Ordering {
match self {
OrdResult::Less => std::cmp::Ordering::Less,
OrdResult::Equal => std::cmp::Ordering::Equal,
OrdResult::Greater => std::cmp::Ordering::Greater,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct SortedSet<T: Ord> {
items: Vec<T>,
}
impl<T: Ord> SortedSet<T> {
pub fn new() -> Self {
Self { items: Vec::new() }
}
pub fn insert(&mut self, item: T) {
match self.items.binary_search(&item) {
Ok(_) => {}
Err(i) => self.items.insert(i, item),
}
}
pub fn contains(&self, item: &T) -> bool {
self.items.binary_search(item).is_ok()
}
pub fn remove(&mut self, item: &T) -> bool {
match self.items.binary_search(item) {
Ok(i) => {
self.items.remove(i);
true
}
Err(_) => false,
}
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn iter(&self) -> std::slice::Iter<'_, T> {
self.items.iter()
}
pub fn union(&self, other: &Self) -> Self
where
T: Clone,
{
let mut result = self.clone();
for item in &other.items {
result.insert(item.clone());
}
result
}
pub fn intersection(&self, other: &Self) -> Self
where
T: Clone,
{
let mut result = Self::new();
for item in &self.items {
if other.contains(item) {
result.insert(item.clone());
}
}
result
}
pub fn difference(&self, other: &Self) -> Self
where
T: Clone,
{
let mut result = Self::new();
for item in &self.items {
if !other.contains(item) {
result.insert(item.clone());
}
}
result
}
}
#[derive(Clone, Debug)]
pub struct SortedMap<K: Ord, V> {
entries: Vec<(K, V)>,
}
impl<K: Ord, V> SortedMap<K, V> {
pub fn new() -> Self {
Self {
entries: Vec::new(),
}
}
pub fn insert(&mut self, key: K, value: V) {
match self.entries.binary_search_by(|(k, _)| k.cmp(&key)) {
Ok(i) => self.entries[i].1 = value,
Err(i) => self.entries.insert(i, (key, value)),
}
}
pub fn get(&self, key: &K) -> Option<&V> {
self.entries
.binary_search_by(|(k, _)| k.cmp(key))
.ok()
.map(|i| &self.entries[i].1)
}
pub fn remove(&mut self, key: &K) -> Option<V> {
self.entries
.binary_search_by(|(k, _)| k.cmp(key))
.ok()
.map(|i| self.entries.remove(i).1)
}
pub fn contains_key(&self, key: &K) -> bool {
self.entries.binary_search_by(|(k, _)| k.cmp(key)).is_ok()
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
self.entries.iter().map(|(k, v)| (k, v))
}
pub fn keys(&self) -> impl Iterator<Item = &K> {
self.entries.iter().map(|(k, _)| k)
}
pub fn values(&self) -> impl Iterator<Item = &V> {
self.entries.iter().map(|(_, v)| v)
}
}
#[allow(dead_code)]
pub struct GaloisPair<A, B, L, R>
where
A: Ord,
B: Ord,
L: Fn(&A) -> B,
R: Fn(&B) -> A,
{
left_adjoint: L,
right_adjoint: R,
_phantom: std::marker::PhantomData<(A, B)>,
}
impl<A, B, L, R> GaloisPair<A, B, L, R>
where
A: Ord,
B: Ord,
L: Fn(&A) -> B,
R: Fn(&B) -> A,
{
pub fn new(left_adjoint: L, right_adjoint: R) -> Self {
Self {
left_adjoint,
right_adjoint,
_phantom: std::marker::PhantomData,
}
}
pub fn left(&self, a: &A) -> B {
(self.left_adjoint)(a)
}
pub fn right(&self, b: &B) -> A {
(self.right_adjoint)(b)
}
pub fn check_galois_condition(&self, a: &A, b: &B) -> bool {
let la = self.left(a);
let rb = self.right(b);
(la <= *b) == (*a <= rb)
}
pub fn closure(&self, a: &A) -> A {
let la = self.left(a);
self.right(&la)
}
pub fn kernel(&self, b: &B) -> B {
let rb = self.right(b);
self.left(&rb)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Permutation {
pub perm: Vec<usize>,
}
impl Permutation {
pub fn identity(n: usize) -> Self {
Self {
perm: (0..n).collect(),
}
}
pub fn from_sort_order<T: Ord>(v: &[T]) -> Self {
let mut indices: Vec<usize> = (0..v.len()).collect();
indices.sort_by(|&a, &b| v[a].cmp(&v[b]));
Self { perm: indices }
}
pub fn apply<T: Clone>(&self, v: &[T]) -> Vec<T> {
self.perm.iter().map(|&i| v[i].clone()).collect()
}
pub fn inverse(&self) -> Self {
let n = self.perm.len();
let mut inv = vec![0usize; n];
for (i, &j) in self.perm.iter().enumerate() {
inv[j] = i;
}
Self { perm: inv }
}
pub fn compose(&self, other: &Self) -> Self {
assert_eq!(self.perm.len(), other.perm.len());
let perm = other.perm.iter().map(|&i| self.perm[i]).collect();
Self { perm }
}
pub fn len(&self) -> usize {
self.perm.len()
}
pub fn is_empty(&self) -> bool {
self.perm.is_empty()
}
pub fn is_identity(&self) -> bool {
self.perm.iter().enumerate().all(|(i, &j)| i == j)
}
}
#[allow(dead_code)]
pub struct MonotoneChain<T: Ord + Clone> {
elements: Vec<T>,
}
impl<T: Ord + Clone> MonotoneChain<T> {
pub fn new() -> Self {
Self {
elements: Vec::new(),
}
}
pub fn push(&mut self, elem: T) -> bool {
if self.elements.is_empty()
|| *self
.elements
.last()
.expect("elements is non-empty: checked by is_empty")
< elem
{
self.elements.push(elem);
true
} else {
false
}
}
pub fn len(&self) -> usize {
self.elements.len()
}
pub fn is_empty(&self) -> bool {
self.elements.is_empty()
}
pub fn min_elem(&self) -> Option<&T> {
self.elements.first()
}
pub fn max_elem(&self) -> Option<&T> {
self.elements.last()
}
pub fn iter(&self) -> std::slice::Iter<'_, T> {
self.elements.iter()
}
pub fn lis_from_slice(v: &[T]) -> Self {
let mut tails: Vec<T> = Vec::new();
for x in v {
let pos = tails.partition_point(|t| t < x);
if pos == tails.len() {
tails.push(x.clone());
} else {
tails[pos] = x.clone();
}
}
let mut chain = Self::new();
for t in tails {
chain.elements.push(t);
}
chain
}
}
#[allow(dead_code)]
pub struct OrderedHeap<T: Ord> {
data: Vec<T>,
}
impl<T: Ord> OrderedHeap<T> {
pub fn new() -> Self {
Self { data: Vec::new() }
}
pub fn push(&mut self, val: T) {
self.data.push(val);
self.sift_up(self.data.len() - 1);
}
pub fn pop(&mut self) -> Option<T> {
if self.data.is_empty() {
return None;
}
let n = self.data.len();
self.data.swap(0, n - 1);
let max = self.data.pop();
if !self.data.is_empty() {
self.sift_down(0);
}
max
}
pub fn peek(&self) -> Option<&T> {
self.data.first()
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
fn sift_up(&mut self, mut i: usize) {
while i > 0 {
let parent = (i - 1) / 2;
if self.data[i] > self.data[parent] {
self.data.swap(i, parent);
i = parent;
} else {
break;
}
}
}
fn sift_down(&mut self, mut i: usize) {
let n = self.data.len();
loop {
let left = 2 * i + 1;
let right = 2 * i + 2;
let mut largest = i;
if left < n && self.data[left] > self.data[largest] {
largest = left;
}
if right < n && self.data[right] > self.data[largest] {
largest = right;
}
if largest == i {
break;
}
self.data.swap(i, largest);
i = largest;
}
}
pub fn from_vec(mut v: Vec<T>) -> Self {
let n = v.len();
let mut heap = Self {
data: std::mem::take(&mut v),
};
if n > 1 {
let start = (n - 2) / 2;
for i in (0..=start).rev() {
heap.sift_down(i);
}
}
heap
}
}