use num_bigint::BigUint;
use std::collections::BTreeSet;
pub fn hamming_bits(a: &[bool], b: &[bool]) -> BigUint {
let count = a.iter().zip(b).filter(|(x, y)| x != y).count();
BigUint::from(count)
}
pub fn symmetric_difference(a: &[usize], b: &[usize]) -> BigUint {
let sa: BTreeSet<usize> = a.iter().copied().collect();
let sb: BTreeSet<usize> = b.iter().copied().collect();
BigUint::from(sa.symmetric_difference(&sb).count())
}
pub fn kendall_tau(a: &[usize], b: &[usize]) -> BigUint {
let n = a.len();
let mut count = 0usize;
for i in 0..n {
for j in (i + 1)..n {
let ord_a = a[i] < a[j];
let ord_b = b[i] < b[j];
if ord_a != ord_b {
count += 1;
}
}
}
BigUint::from(count)
}
pub fn l1_u64(a: &[u64], b: &[u64]) -> BigUint {
let mut acc = BigUint::from(0u32);
for (x, y) in a.iter().zip(b) {
acc += BigUint::from(x.abs_diff(*y));
}
acc
}
pub fn l1_i64(a: &[i64], b: &[i64]) -> BigUint {
let mut acc = BigUint::from(0u32);
for (x, y) in a.iter().zip(b) {
let d = (*x as i128 - *y as i128).unsigned_abs();
acc += BigUint::from(d);
}
acc
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hamming_counts_differences() {
assert_eq!(
hamming_bits(&[true, false, true], &[true, true, false]),
BigUint::from(2u32)
);
}
#[test]
fn symmetric_difference_counts() {
assert_eq!(
symmetric_difference(&[0, 1, 2], &[1, 2, 3]),
BigUint::from(2u32)
);
}
#[test]
fn kendall_tau_basic() {
assert_eq!(kendall_tau(&[0, 1, 2], &[2, 1, 0]), BigUint::from(3u32));
assert_eq!(kendall_tau(&[0, 1, 2], &[0, 1, 2]), BigUint::from(0u32));
}
#[test]
fn l1_distances() {
assert_eq!(l1_u64(&[1, 5, 3], &[4, 1, 3]), BigUint::from(7u32));
assert_eq!(l1_i64(&[-2, 3], &[1, -1]), BigUint::from(7u32));
}
}