use std;
use std::cmp::Ordering;
use std::convert::AsRef;
#[derive(Clone, Debug)]
pub struct Permutation {
forward: bool,
indices: Vec<usize>,
}
impl std::cmp::PartialEq for Permutation {
fn eq(&self, other: &Permutation) -> bool {
if self.forward == other.forward {
self.indices == other.indices
} else {
self.indices
.iter()
.enumerate()
.all(|(i, &j)| other.indices[j] == i)
}
}
}
impl std::cmp::Eq for Permutation {}
impl<'a, 'b> std::ops::Mul<&'b Permutation> for &'a Permutation {
type Output = Permutation;
fn mul(self, rhs: &'b Permutation) -> Self::Output {
match (self.forward, rhs.forward) {
(_, false) => Permutation::oneline(self.apply_slice(&rhs.indices)).inverse(),
(false, true) => return self * &(rhs * &Permutation::one(self.len())),
(true, true) => Permutation {
forward: true,
indices: rhs.apply_inv_slice(&self.indices),
},
}
}
}
impl Permutation {
#[deprecated(since = "0.4.0", note = "Please replace with oneline(vec).inverse()")]
pub fn from_vec<V>(vec: V) -> Permutation
where
V: Into<Vec<usize>>,
{
let result = Permutation {
forward: false,
indices: vec.into(),
};
debug_assert!(result.valid());
return result;
}
pub fn oneline<V>(vec: V) -> Permutation
where
V: Into<Vec<usize>>,
{
let result = Permutation {
forward: true,
indices: vec.into(),
};
debug_assert!(result.valid());
return result;
}
pub fn assign_from_sort<T, S>(&mut self, slice: S)
where
T: Ord,
S: AsRef<[T]>,
{
let s = slice.as_ref();
assert_eq!(self.len(), s.len());
self.indices.sort_by_key(|&i| &s[i]);
}
pub fn assign_from_sort_by<T, S, F>(&mut self, slice: S, mut compare: F)
where
S: AsRef<[T]>,
F: FnMut(&T, &T) -> Ordering,
{
let s = slice.as_ref();
assert_eq!(self.indices.len(), s.len());
self.indices.sort_by(|&i, &j| compare(&s[i], &s[j]));
}
pub fn assign_from_sort_by_key<T, S, B, F>(&mut self, slice: S, mut f: F)
where
B: Ord,
S: AsRef<[T]>,
F: FnMut(&T) -> B,
{
let s = slice.as_ref();
assert_eq!(self.indices.len(), s.len());
self.indices.sort_by_key(|&i| f(&s[i]));
}
pub fn one(len: usize) -> Permutation {
Permutation {
forward: false,
indices: (0..len).collect(),
}
}
pub fn len(&self) -> usize {
return self.indices.len();
}
pub fn valid(&self) -> bool {
let mut sorted = self.indices.clone();
sorted.sort();
return sorted.iter().enumerate().all(|(i, &j)| i == j);
}
pub fn inverse(mut self) -> Permutation {
self.forward ^= true;
return self;
}
pub fn normalize(self, backward: bool) -> Permutation {
if self.forward ^ backward {
self
} else {
let len = self.len();
if backward {
&self * &Permutation::one(len)
} else {
(&self.inverse() * &Permutation::one(len)).inverse()
}
}
}
fn apply_idx_fwd(&self, idx: usize) -> usize {
self.indices.iter().position(|&v| v == idx).unwrap()
}
fn apply_idx_bkwd(&self, idx: usize) -> usize {
self.indices[idx]
}
pub fn apply_idx(&self, idx: usize) -> usize {
match self.forward {
false => self.apply_idx_fwd(idx),
true => self.apply_idx_bkwd(idx),
}
}
pub fn apply_inv_idx(&self, idx: usize) -> usize {
match self.forward {
true => self.apply_idx_fwd(idx),
false => self.apply_idx_bkwd(idx),
}
}
fn apply_slice_fwd<T: Clone, S>(&self, slice: S) -> Vec<T>
where
S: AsRef<[T]>,
{
let s = slice.as_ref();
self.indices.iter().map(|&idx| s[idx].clone()).collect()
}
fn apply_slice_bkwd<T: Clone, S>(&self, slice: S) -> Vec<T>
where
S: AsRef<[T]>,
{
let s = slice.as_ref();
let mut other: Vec<T> = s.to_vec();
for (i, idx) in self.indices.iter().enumerate() {
other[*idx] = s[i].clone();
}
return other;
}
#[inline(always)]
fn toggle_mark_idx(idx: usize) -> usize {
idx ^ isize::min_value() as usize
}
#[inline(always)]
fn idx_is_marked(idx: usize) -> bool {
(idx & (isize::min_value() as usize)) != 0
}
fn apply_slice_bkwd_in_place<T, S>(&mut self, slice: &mut S)
where
S: AsMut<[T]> + ?Sized,
{
let s = slice.as_mut();
assert_eq!(s.len(), self.len());
assert!(s.len() <= isize::max_value() as usize);
for idx in self.indices.iter() {
debug_assert!(!Self::idx_is_marked(*idx));
}
for i in 0..self.indices.len() {
let i_idx = self.indices[i];
if Self::idx_is_marked(i_idx) {
continue;
}
let mut j = i;
let mut j_idx = i_idx;
while j_idx != i {
self.indices[j] = Self::toggle_mark_idx(j_idx);
s.swap(j, j_idx);
j = j_idx;
j_idx = self.indices[j];
}
self.indices[j] = Self::toggle_mark_idx(j_idx);
}
for idx in self.indices.iter_mut() {
debug_assert!(Self::idx_is_marked(*idx));
*idx = Self::toggle_mark_idx(*idx);
}
}
fn apply_slice_fwd_in_place<T, S>(&mut self, slice: &mut S)
where
S: AsMut<[T]> + ?Sized,
{
let s = slice.as_mut();
assert_eq!(s.len(), self.len());
assert!(s.len() <= isize::max_value() as usize);
for idx in self.indices.iter() {
debug_assert!(!Self::idx_is_marked(*idx));
}
for i in 0..self.indices.len() {
let i_idx = self.indices[i];
if Self::idx_is_marked(i_idx) {
continue;
}
let mut j = i;
let mut j_idx = i_idx;
while j_idx != i {
self.indices[j] = Self::toggle_mark_idx(j_idx);
s.swap(i, j_idx);
j = j_idx;
j_idx = self.indices[j];
}
self.indices[j] = Self::toggle_mark_idx(j_idx);
}
for idx in self.indices.iter_mut() {
debug_assert!(Self::idx_is_marked(*idx));
*idx = Self::toggle_mark_idx(*idx);
}
}
#[must_use]
pub fn apply_slice<T: Clone, S>(&self, slice: S) -> Vec<T>
where
S: AsRef<[T]>,
{
let s = slice.as_ref();
assert_eq!(s.len(), self.len());
match self.forward {
false => self.apply_slice_fwd(s),
true => self.apply_slice_bkwd(s),
}
}
#[must_use]
pub fn apply_inv_slice<T: Clone, S>(&self, slice: S) -> Vec<T>
where
S: AsRef<[T]>,
{
let s = slice.as_ref();
assert_eq!(s.len(), self.len());
match self.forward {
false => self.apply_slice_bkwd(s),
true => self.apply_slice_fwd(s),
}
}
pub fn apply_slice_in_place<T, S>(&mut self, slice: &mut S)
where
S: AsMut<[T]> + ?Sized,
{
match self.forward {
false => self.apply_slice_bkwd_in_place(slice),
true => self.apply_slice_fwd_in_place(slice),
}
}
pub fn apply_inv_slice_in_place<T, S>(&mut self, slice: &mut S)
where
S: AsMut<[T]> + ?Sized,
{
match self.forward {
false => self.apply_slice_fwd_in_place(slice),
true => self.apply_slice_bkwd_in_place(slice),
}
}
}
pub fn sort<T, S>(slice: S) -> Permutation
where
T: Ord,
S: AsRef<[T]>,
{
let s = slice.as_ref();
let mut permutation = Permutation::one(s.len());
permutation.indices.sort_by_key(|&i| &s[i]);
return permutation;
}
pub fn sort_unstable<T, S>(slice: S) -> Permutation
where
T: Ord,
S: AsRef<[T]>,
{
let s = slice.as_ref();
let mut permutation = Permutation::one(s.len());
permutation.indices.sort_unstable_by_key(|&i| &s[i]);
return permutation;
}
pub fn sort_by<T, S, F>(slice: S, mut compare: F) -> Permutation
where
S: AsRef<[T]>,
F: FnMut(&T, &T) -> Ordering,
{
let s = slice.as_ref();
let mut permutation = Permutation::one(s.len());
permutation.indices.sort_by(|&i, &j| compare(&s[i], &s[j]));
return permutation;
}
pub fn sort_unstable_by<T, S, F>(slice: S, mut compare: F) -> Permutation
where
S: AsRef<[T]>,
F: FnMut(&T, &T) -> Ordering,
{
let s = slice.as_ref();
let mut permutation = Permutation::one(s.len());
permutation
.indices
.sort_unstable_by(|&i, &j| compare(&s[i], &s[j]));
return permutation;
}
pub fn sort_by_key<T, S, B, F>(slice: S, mut f: F) -> Permutation
where
B: Ord,
S: AsRef<[T]>,
F: FnMut(&T) -> B,
{
let s = slice.as_ref();
let mut permutation = Permutation::one(s.len());
permutation.indices.sort_by_key(|&i| f(&s[i]));
return permutation;
}
pub fn sort_unstable_by_key<T, S, B, F>(slice: S, mut f: F) -> Permutation
where
B: Ord,
S: AsRef<[T]>,
F: FnMut(&T) -> B,
{
let s = slice.as_ref();
let mut permutation = Permutation::one(s.len());
permutation.indices.sort_unstable_by_key(|&i| f(&s[i]));
return permutation;
}
#[cfg(test)]
mod tests {
use permutation;
use permutation::Permutation;
#[test]
fn basics() {
let p1 = Permutation::one(5);
let p2 = Permutation::one(5);
assert!(p1.valid());
assert_eq!(p1, p2);
let p3 = Permutation::one(6);
assert!(p1 != p3);
assert_eq!(&p1 * &p2, p1);
assert_eq!(p1.clone().inverse(), p1);
}
#[test]
#[allow(deprecated)]
fn from_vec_oneline() {
let p_from_vec = Permutation::from_vec(vec![0, 1, 2]);
let p_oneline = Permutation::oneline(vec![0, 1, 2]);
assert_eq!(p_from_vec, p_oneline);
}
#[test]
fn oneline() {
let p = Permutation::oneline(vec![0, 1, 2]);
assert!(p.valid());
}
#[test]
fn oneline_slice() {
let v = vec![0, 1, 2];
let p = Permutation::oneline(&v[..]);
assert!(p.valid());
}
#[test]
fn oneline_array() {
let p = Permutation::oneline([0, 1, 2]);
assert!(p.valid());
}
#[test]
fn powers() {
let id = Permutation::one(3);
let p1 = Permutation::oneline([1, 0, 2]);
let square = &p1 * &p1;
assert_eq!(square, id);
let cube = &p1 * □
assert_eq!(cube, p1);
}
#[test]
fn prod() {
let p1 = Permutation::oneline([1, 0, 2]);
let p2 = Permutation::oneline([0, 2, 1]);
let prod = &p1 * &p2;
assert_eq!(prod, Permutation::oneline([1, 2, 0]));
}
#[test]
fn len() {
let p1 = Permutation::oneline([1, 0, 2]);
assert_eq!(p1.len(), 3)
}
fn check_not_equal_inverses(p2: &Permutation, p3: &Permutation) {
assert!(*p2 != *p3);
assert_eq!(p2 * p3, Permutation::one(p2.len()));
assert_eq!(p3 * p2, Permutation::one(p2.len()));
assert_eq!(*p2, p3.clone().inverse());
assert_eq!(p2.clone().inverse(), *p3);
assert!(p2.clone().inverse() != p3.clone().inverse());
assert!(p2 * &p3.clone().inverse() != Permutation::one(p2.len()));
assert!(&p2.clone().inverse() * p3 != Permutation::one(p2.len()));
}
#[test]
fn inverse() {
let p1 = Permutation::oneline([1, 0, 2]);
let rev = p1.clone().inverse();
assert_eq!(p1, rev);
let p2 = Permutation::oneline([1, 2, 0, 4, 3]);
let p3 = Permutation::oneline([2, 0, 1, 4, 3]);
check_not_equal_inverses(&p2, &p3);
println!(
"{:?}, {:?}, {:?}",
p2.clone().inverse(),
p3.clone().inverse(),
&p2.clone().inverse() * &p3.clone().inverse()
);
assert_eq!(
&p2.clone().inverse() * &p3.clone().inverse(),
Permutation::one(p2.len())
);
let p4 = Permutation::oneline([1, 2, 0, 3, 4]);
let p5 = Permutation::oneline([2, 0, 1, 4, 3]);
assert!(p4 != p5);
assert!(p4 != p5.clone().inverse());
assert!(p4.clone().inverse() != p5);
assert!(p4.clone().inverse() != p5.clone().inverse());
assert!(&p4 * &p5 != Permutation::one(p4.len()));
assert!(&p5 * &p4 != Permutation::one(p4.len()));
assert!(&p4.clone().inverse() * &p5 != Permutation::one(p4.len()));
assert!(&p4 * &p5.clone().inverse() != Permutation::one(p4.len()));
}
#[test]
fn sort_slice() {
let elems = ['a', 'b', 'g', 'e', 'f'];
let perm = permutation::sort(&elems[..]);
println!("{:?}", perm);
assert_eq!(perm, Permutation::oneline([0, 1, 4, 2, 3]));
}
#[test]
fn sort_array() {
let elems = ['a', 'b', 'e', 'g', 'f'];
permutation::sort(elems);
}
#[test]
fn sort_array_ref() {
let elems = ['a', 'b', 'e', 'g', 'f'];
permutation::sort(&elems);
}
#[test]
fn sort_vec() {
let elems = vec!['a', 'b', 'e', 'g', 'f'];
permutation::sort(&elems);
}
#[test]
fn strings() {
let elems = ["doggie", "cat", "doggo", "dog", "doggies", "god"];
let perm = permutation::sort(&elems);
assert_eq!(perm, Permutation::oneline([2, 0, 4, 1, 3, 5]));
assert!(perm.apply_slice(&elems) == ["cat", "dog", "doggie", "doggies", "doggo", "god"]);
let parallel = ["doggie1", "cat1", "doggo1", "dog1", "doggies1", "god1"];
let par_permuted = perm.apply_slice(¶llel);
println!("{:?}", par_permuted);
assert_eq!(
par_permuted,
["cat1", "dog1", "doggie1", "doggies1", "doggo1", "god1"]
);
assert_eq!(perm.apply_inv_slice(par_permuted), parallel);
}
#[test]
fn by_key() {
let arr = [1, 10, 9, 8];
let perm = permutation::sort_by_key(arr, |i| -i);
assert_eq!(perm, Permutation::oneline([3, 0, 1, 2]));
}
#[test]
fn by_cmp() {
let arr = ["aaabaab", "aba", "cas", "aaab"];
let perm = permutation::sort_by(arr, |a, b| a.cmp(b));
assert_eq!(perm, Permutation::oneline([1, 2, 3, 0]));
}
#[test]
fn by_partially_ordered_cmp() {
let arr = [1.0, 5.0, 3.0, 2.0, 8.0];
let perm = permutation::sort_by(arr, |a, b| a.partial_cmp(b).unwrap());
assert!(perm == Permutation::oneline([0, 3, 2, 1, 4]));
}
#[test]
fn apply_array() {
let arr = [1, 10, 9, 8];
let perm = permutation::sort_by_key(arr, |i| -i);
assert_eq!(perm, Permutation::oneline([3, 0, 1, 2]));
}
#[test]
fn indices() {
let arr = [100, 10, 1, 1000];
let perm = permutation::sort_by_key(arr, |x| -x);
println!("{:?}", perm.apply_inv_idx(0));
assert_eq!(perm.apply_inv_idx(0), 3);
assert_eq!(perm.apply_idx(3), 0);
assert_eq!(perm.apply_inv_idx(1), 0);
assert_eq!(perm.apply_idx(0), 1);
assert_eq!(perm.apply_inv_idx(2), 1);
assert_eq!(perm.apply_idx(1), 2);
assert_eq!(perm.apply_inv_idx(3), 2);
assert_eq!(perm.apply_idx(2), 3);
}
#[test]
fn normalize() {
let arr = [100, 10, 1, 1000];
let perm = permutation::sort_by_key(arr, |x| -x);
let f = perm.clone().normalize(false);
let b = perm.clone().normalize(true);
assert_eq!(perm, f);
assert_eq!(f, b);
for idx in 0..perm.len() {
assert_eq!(perm.apply_idx(idx), f.apply_idx(idx));
assert_eq!(f.apply_idx(idx), b.apply_idx(idx));
assert_eq!(perm.apply_inv_idx(idx), f.apply_inv_idx(idx));
assert_eq!(f.apply_inv_idx(idx), b.apply_inv_idx(idx));
}
let inv = perm.clone().inverse();
let fi = inv.clone().normalize(false);
let bi = inv.clone().normalize(true);
assert_eq!(inv, fi);
assert_eq!(fi, bi);
for idx in 0..perm.len() {
assert_eq!(inv.apply_idx(idx), fi.apply_idx(idx));
assert_eq!(fi.apply_idx(idx), bi.apply_idx(idx));
assert_eq!(inv.apply_inv_idx(idx), fi.apply_inv_idx(idx));
assert_eq!(fi.apply_inv_idx(idx), bi.apply_inv_idx(idx));
}
}
#[test]
fn normalize_inv() {
let p1 = Permutation::oneline([1, 0, 2]);
let rev = p1.clone().inverse();
assert_eq!(p1, rev);
let mut p2 = Permutation::oneline([2, 0, 1, 4, 3]);
let mut p3 = Permutation::oneline([1, 2, 0, 4, 3]);
p2 = p2.normalize(false);
p3 = p3.normalize(false);
check_not_equal_inverses(&p2, &p3);
p2 = p2.normalize(true);
p3 = p3.normalize(true);
check_not_equal_inverses(&p2, &p3);
p2 = p2.normalize(true);
p3 = p3.normalize(false);
check_not_equal_inverses(&p2, &p3);
p2 = p2.normalize(false);
p3 = p3.normalize(true);
check_not_equal_inverses(&p2, &p3);
}
#[test]
fn apply_slice_in_place_vec() {
let mut p = Permutation::oneline([1, 2, 0, 4, 3]);
let mut vec = vec!['a', 'b', 'c', 'd', 'e'];
p.apply_slice_in_place(&mut vec);
assert_eq!(vec, vec!['c', 'a', 'b', 'e', 'd']);
}
#[test]
fn apply_unnorm_in_place() {
let mut p = Permutation::oneline([1, 2, 0, 4, 3]).normalize(false);
let p_old = p.clone();
let mut vec = ['a', 'b', 'c', 'd', 'e'];
p.apply_slice_in_place(&mut vec);
assert_eq!(vec, ['c', 'a', 'b', 'e', 'd']);
assert_eq!(p.indices, p_old.indices);
assert_eq!(p.forward, p_old.forward);
}
#[test]
fn apply_norm_in_place() {
let mut p = Permutation::oneline([1, 2, 0, 4, 3]).normalize(true);
let p_old = p.clone();
let mut vec = ['a', 'b', 'c', 'd', 'e'];
p.apply_slice_in_place(&mut vec);
assert_eq!(vec, ['c', 'a', 'b', 'e', 'd']);
assert_eq!(p.indices, p_old.indices);
assert_eq!(p.forward, p_old.forward);
}
#[test]
fn apply_inv_unnorm_place() {
let mut p = Permutation::oneline([1, 2, 0, 4, 3])
.inverse()
.normalize(false);
let p_old = p.clone();
let mut vec = ['c', 'a', 'b', 'e', 'd'];
p.apply_slice_in_place(&mut vec);
assert_eq!(vec, ['a', 'b', 'c', 'd', 'e']);
assert_eq!(p.indices, p_old.indices);
assert_eq!(p.forward, p_old.forward);
}
#[test]
fn apply_inv_norm_in_place() {
let mut p = Permutation::oneline([1, 2, 0, 4, 3])
.inverse()
.normalize(true);
let p_old = p.clone();
let mut vec = ['c', 'a', 'b', 'e', 'd'];
p.apply_slice_in_place(&mut vec);
assert_eq!(vec, ['a', 'b', 'c', 'd', 'e']);
assert_eq!(p.indices, p_old.indices);
assert_eq!(p.forward, p_old.forward);
}
}