use super::EqSignature;
use algebraeon_macros::{signature_meta_trait, skip_meta};
use std::{borrow::Borrow, cmp::Ordering};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MergedSource {
First,
Second,
}
struct VecMerger<'s, X, O: OrdSignature, K: Fn(&X) -> &O::Set> {
ordering: &'s O,
i: usize,
a: Vec<Option<X>>,
j: usize,
b: Vec<Option<X>>,
key: K,
}
impl<'s, X, O: OrdSignature + 's, K: Fn(&X) -> &O::Set> VecMerger<'s, X, O, K> {
fn new(ordering: &'s O, a: Vec<X>, b: Vec<X>, key: K) -> Self {
Self {
ordering,
i: 0,
a: a.into_iter().map(|x| Some(x)).collect(),
j: 0,
b: b.into_iter().map(|x| Some(x)).collect(),
key,
}
}
}
impl<'s, X, O: OrdSignature + 's, K: Fn(&X) -> &O::Set> Iterator for VecMerger<'s, X, O, K> {
type Item = (MergedSource, X);
fn next(&mut self) -> Option<Self::Item> {
match (self.i < self.a.len(), self.j < self.b.len()) {
(true, true) => {
match self.ordering.cmp(
(self.key)(self.a[self.i].as_ref().unwrap()).borrow(),
(self.key)(self.b[self.j].as_ref().unwrap()).borrow(),
) {
Ordering::Less | Ordering::Equal => {
let a_item = self.a[self.i].take().unwrap();
self.i += 1;
Some((MergedSource::First, a_item))
}
Ordering::Greater => {
let b_item = self.b[self.j].take().unwrap();
self.j += 1;
Some((MergedSource::Second, b_item))
}
}
}
(true, false) => {
let a_item = self.a[self.i].take().unwrap();
self.i += 1;
Some((MergedSource::First, a_item))
}
(false, true) => {
let b_item = self.b[self.j].take().unwrap();
self.j += 1;
Some((MergedSource::Second, b_item))
}
(false, false) => None,
}
}
}
use super::MetaType;
#[signature_meta_trait]
pub trait PartialOrdSignature: EqSignature {
fn partial_cmp(&self, a: &Self::Set, b: &Self::Set) -> Option<Ordering>;
}
#[signature_meta_trait]
pub trait OrdSignature: PartialOrdSignature {
fn cmp(&self, a: &Self::Set, b: &Self::Set) -> Ordering;
fn max(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
let c = self.cmp(a, b);
match c {
Ordering::Less | Ordering::Equal => b.clone(),
Ordering::Greater => a.clone(),
}
}
fn min(&self, a: &Self::Set, b: &Self::Set) -> Self::Set {
let c = self.cmp(a, b);
match c {
Ordering::Less | Ordering::Equal => a.clone(),
Ordering::Greater => b.clone(),
}
}
fn is_sorted(&self, a: &[impl Borrow<Self::Set>]) -> bool {
for i in 1..a.len() {
if self.cmp(a[i - 1].borrow(), a[i].borrow()) == Ordering::Greater {
return false;
}
}
true
}
fn is_sorted_by_key<X>(&self, a: &[X], key: impl Fn(&X) -> &Self::Set) -> bool {
self.is_sorted(&a.iter().map(key).collect::<Vec<_>>())
}
fn is_sorted_and_unique(&self, a: &[impl Borrow<Self::Set>]) -> bool {
for i in 1..a.len() {
if self.cmp(a[i - 1].borrow(), a[i].borrow()) != Ordering::Less {
return false;
}
}
true
}
fn is_sorted_and_unique_by_key<X>(&self, a: &[X], key: impl Fn(&X) -> &Self::Set) -> bool {
self.is_sorted_and_unique(&a.iter().map(key).collect::<Vec<_>>())
}
fn binary_search(&self, v: &[impl Borrow<Self::Set>], target: &Self::Set) -> bool {
self.binary_search_by_key(v, target, |x| x.borrow())
.is_some()
}
fn binary_search_by_key<'x, X>(
&self,
v: &'x [X],
target: &Self::Set,
key: impl Fn(&X) -> &Self::Set,
) -> Option<&'x X> {
debug_assert!(self.is_sorted_by_key(v, &key));
if v.is_empty() {
return None;
}
let mut a = 0;
let mut b = v.len() - 1;
if self.equal(target, key(&v[a])) {
return Some(&v[a]);
}
if self.equal(target, key(&v[b])) {
return Some(&v[b]);
}
while b - a >= 2 {
println!("{:?} {:?}", a, b);
let m = (a + b) / 2;
let m_key = key(&v[m]);
match self.cmp(target, m_key) {
Ordering::Less => b = m,
Ordering::Equal => {
return Some(&v[m]);
}
Ordering::Greater => a = m,
}
}
None
}
#[skip_meta]
fn merge_sorted<'s, S: Borrow<Self::Set> + 's>(
&'s self,
a: Vec<S>,
b: Vec<S>,
) -> impl Iterator<Item = (MergedSource, S)> {
self.merge_sorted_by_key(a, b, |x| (*x).borrow())
}
#[skip_meta]
fn merge_sorted_by_key<X>(
&self,
a: Vec<X>,
b: Vec<X>,
key: impl Fn(&X) -> &Self::Set,
) -> impl Iterator<Item = (MergedSource, X)> {
debug_assert!(self.is_sorted_by_key(&a.iter().collect::<Vec<_>>(), |x| key(x)));
debug_assert!(self.is_sorted_by_key(&b.iter().collect::<Vec<_>>(), |x| key(x)));
VecMerger::new(self, a, b, key)
}
fn sort<S: Borrow<Self::Set>>(&self, a: Vec<S>) -> Vec<S> {
self.sort_by_key(a, &|x| x.borrow())
}
#[skip_meta]
fn sort_by_key<X>(&self, mut a: Vec<X>, key: &impl Fn(&X) -> &Self::Set) -> Vec<X> {
match a.len() {
0 | 1 => a,
2 => match self.cmp(key(&a[0]).borrow(), key(&a[1]).borrow()) {
Ordering::Less | Ordering::Equal => a,
Ordering::Greater => {
a.swap(0, 1);
a
}
},
n => {
let k = n / 2;
let a1 = a.split_off(k);
let a0 = a;
let a0_sorted = self.sort_by_key(a0, key);
let a1_sorted = self.sort_by_key(a1, key);
self.merge_sorted_by_key(a0_sorted, a1_sorted, key)
.map(|(_, s)| s)
.collect()
}
}
}
fn sort_by_cached_by<X: 'static>(&self, a: Vec<X>, key: impl Fn(&X) -> Self::Set) -> Vec<X>
where
Self::Set: 'static,
{
let mut a = a.into_iter().map(|x| (x, None)).collect::<Vec<_>>();
for i in 0..a.len() {
let (x, k) = a.get_mut(i).unwrap();
*k = Some(key(x));
}
self.sort_by_key(a, &|(_, k)| k.as_ref().unwrap())
.into_iter()
.map(|(x, _)| x)
.collect()
}
}
#[cfg(test)]
mod tests {
use crate::structure::*;
use super::*;
#[derive(Debug, Clone, PartialEq, Eq)]
struct UsizeStructure {}
impl Signature for UsizeStructure {}
impl SetSignature for UsizeStructure {
type Set = usize;
fn validate_element(&self, _x: &Self::Set) -> Result<(), String> {
Ok(())
}
}
impl EqSignature for UsizeStructure {
fn equal(&self, a: &Self::Set, b: &Self::Set) -> bool {
a == b
}
}
impl PartialOrdSignature for UsizeStructure {
fn partial_cmp(&self, a: &Self::Set, b: &Self::Set) -> Option<Ordering> {
Some(self.cmp(a, b))
}
}
impl OrdSignature for UsizeStructure {
fn cmp(&self, a: &Self::Set, b: &Self::Set) -> Ordering {
usize::cmp(a, b)
}
}
#[test]
fn ordering_structure() {
let s = UsizeStructure {};
assert_eq!(s.cmp(&2, &2), Ordering::Equal);
assert_eq!(s.cmp(&1, &2), Ordering::Less);
assert_eq!(s.cmp(&2, &1), Ordering::Greater);
assert!(s.is_sorted(&Vec::<usize>::new()));
assert!(s.is_sorted(&[7]));
assert!(s.is_sorted(&[1, 2]));
assert!(!s.is_sorted(&[2, 1]));
assert!(s.is_sorted(&[1, 2, 3]));
assert!(s.is_sorted(&[1, 1, 1]));
assert!(!s.is_sorted(&[1, 2, 1]));
assert_eq!(
s.merge_sorted(Vec::<usize>::new(), Vec::<usize>::new())
.collect::<Vec<_>>(),
vec![]
);
{
let a = vec![2, 4, 5, 7];
let b = vec![1, 3, 6, 7, 8];
let c = s.merge_sorted(a, b).collect::<Vec<_>>();
assert_eq!(
c,
vec![
(MergedSource::Second, 1),
(MergedSource::First, 2),
(MergedSource::Second, 3),
(MergedSource::First, 4),
(MergedSource::First, 5),
(MergedSource::Second, 6),
(MergedSource::First, 7),
(MergedSource::Second, 7),
(MergedSource::Second, 8)
]
);
}
assert_eq!(s.sort(Vec::<usize>::new()), Vec::<usize>::new());
assert_eq!(s.sort(vec![7]), vec![7]);
assert_eq!(s.sort(vec![7, 7]), vec![7, 7]);
assert_eq!(s.sort(vec![1, 2]), vec![1, 2]);
assert_eq!(s.sort(vec![2, 1]), vec![1, 2]);
assert_eq!(s.sort(vec![7, 6, 5, 4, 3, 2, 1]), vec![1, 2, 3, 4, 5, 6, 7]);
assert_eq!(
s.sort(vec![3, 3, 2, 2, 2, 1, 1, 1, 1]),
vec![1, 1, 1, 1, 2, 2, 2, 3, 3]
);
assert_eq!(
s.sort_by_cached_by(vec![3, 3, 2, 2, 2, 1, 1, 1, 1], |x| 5 - x),
vec![3, 3, 2, 2, 2, 1, 1, 1, 1]
);
let v = vec![1, 2, 3, 3, 3, 4, 4, 5, 7, 8, 9, 10, 11];
assert!(!s.binary_search(&v, &0));
assert!(s.binary_search(&v, &1));
assert!(s.binary_search(&v, &3));
assert!(s.binary_search(&v, &4));
assert!(s.binary_search(&v, &5));
assert!(!s.binary_search(&v, &6));
assert!(s.binary_search(&v, &7));
assert!(s.binary_search(&v, &11));
assert!(!s.binary_search(&v, &12));
}
}