From f964e7a38bcb971687e85dfb5acf1e250f8e1bca Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 21 May 2023 09:36:16 -0700 Subject: [PATCH 01/10] use Self --- src/permutation.rs | 54 +++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index 020b73f..25cc1c7 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -36,21 +36,21 @@ fn is_permutation(v: &[usize]) -> bool { pub struct Permutation(Box<[usize]>); impl Permutation { /// Returns the identity permutation of n elements. - pub fn identity(n: usize) -> Permutation { - Permutation((0..n).collect::>()) + pub fn identity(n: usize) -> Self { + Self((0..n).collect()) } /// Returns the permutation of n elements which rotates r steps to the left. pub fn rotation_left(n: usize, r: usize) -> Permutation { - Permutation((0..n).map(|i| (i + r) % n).collect::>()) + Self((0..n).map(|i| (i + r) % n).collect()) } /// Returns the permutation of n elements which rotates r steps to the right. - pub fn rotation_right(n: usize, r: usize) -> Permutation { - Permutation::rotation_left(n, n - (r % n)) + pub fn rotation_right(n: usize, r: usize) -> Self { + Self::rotation_left(n, n - (r % n)) } /// Returns the permutation of n elements which exchanges the elements at i and j. - pub fn transposition(n: usize, i: usize, j: usize) -> Permutation { + pub fn transposition(n: usize, i: usize, j: usize) -> Self { assert!(i < n && j < n); - Permutation( + Self( (0..n) .map(|k| { if k == i { @@ -61,7 +61,7 @@ impl Permutation { k } }) - .collect::>(), + .collect(), ) } @@ -155,13 +155,13 @@ impl Permutation { } } impl ops::Mul for Permutation { - type Output = Permutation; - fn mul(self, other: Permutation) -> Self::Output { + type Output = Self; + fn mul(self, other: Self) -> Self { assert_eq!(self.len(), other.len()); - Permutation( + Self( (0..self.len()) .map(|i| other.apply(self.apply(i))) - .collect::>(), + .collect(), ) } } @@ -172,18 +172,18 @@ impl ops::Mul for &Permutation { Permutation( (0..self.len()) .map(|i| other.apply(self.apply(i))) - .collect::>(), + .collect(), ) } } -impl ops::Mul<&Permutation> for Permutation { - type Output = Permutation; - fn mul(self, other: &Permutation) -> Self::Output { +impl ops::Mul<&Self> for Permutation { + type Output = Self; + fn mul(self, other: &Self) -> Self::Output { assert_eq!(self.len(), other.len()); - Permutation( + Self( (0..self.len()) .map(|i| other.apply(self.apply(i))) - .collect::>(), + .collect(), ) } } @@ -194,15 +194,15 @@ impl ops::Mul<&Permutation> for &Permutation { Permutation( (0..self.len()) .map(|i| other.apply(self.apply(i))) - .collect::>(), + .collect(), ) } } impl TryFrom> for Permutation { type Error = TryFromError; - fn try_from(v: Vec) -> Result { + fn try_from(v: Vec) -> Result { if is_permutation(&v) { - Ok(Permutation(v.into_boxed_slice())) + Ok(Self(v.into_boxed_slice())) } else { Err(TryFromError) } @@ -210,9 +210,9 @@ impl TryFrom> for Permutation { } impl<'a> TryFrom<&'a Vec> for Permutation { type Error = TryFromError; - fn try_from(v: &'a Vec) -> Result { + fn try_from(v: &'a Vec) -> Result { if is_permutation(v) { - Ok(Permutation(Box::from(&v[..]))) + Ok(Self(Box::from(&v[..]))) } else { Err(TryFromError) } @@ -220,9 +220,9 @@ impl<'a> TryFrom<&'a Vec> for Permutation { } impl TryFrom<&[usize]> for Permutation { type Error = TryFromError; - fn try_from(a: &[usize]) -> Result { + fn try_from(a: &[usize]) -> Result { if is_permutation(a) { - Ok(Permutation(Box::from(a))) + Ok(Self(Box::from(a))) } else { Err(TryFromError) } @@ -230,9 +230,9 @@ impl TryFrom<&[usize]> for Permutation { } impl TryFrom<&[usize; N]> for Permutation { type Error = TryFromError; - fn try_from(a: &[usize; N]) -> Result { + fn try_from(a: &[usize; N]) -> Result { if is_permutation(a) { - Ok(Permutation(Box::from(&a[..]))) + Ok(Self(Box::from(&a[..]))) } else { Err(TryFromError) } From 49eef3dc48761081df22be5a3ad8d534e41529fc Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 21 May 2023 09:39:07 -0700 Subject: [PATCH 02/10] nitpicks --- src/permutation.rs | 21 ++++++++++----------- src/permutations.rs | 8 ++++---- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index 25cc1c7..a2098cd 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -34,13 +34,14 @@ fn is_permutation(v: &[usize]) -> bool { /// A permutation. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Permutation(Box<[usize]>); + impl Permutation { /// Returns the identity permutation of n elements. pub fn identity(n: usize) -> Self { Self((0..n).collect()) } /// Returns the permutation of n elements which rotates r steps to the left. - pub fn rotation_left(n: usize, r: usize) -> Permutation { + pub fn rotation_left(n: usize, r: usize) -> Self { Self((0..n).map(|i| (i + r) % n).collect()) } /// Returns the permutation of n elements which rotates r steps to the right. @@ -69,11 +70,11 @@ impl Permutation { /// /// Uses a uniform distribution. #[cfg(feature = "random")] - pub fn random(rng: &mut R, n: usize) -> Permutation + pub fn random(rng: &mut R, n: usize) -> Self where R: Rng, { - let ps = Permutations::new(n); + let ps = Self::new(n); let i = rng.gen_range(0..ps.len()); ps.get(i).expect("random index out of range") } @@ -84,18 +85,16 @@ impl Permutation { /// Returns a vector permuted by this permutation. pub fn permute(&self, v: &[T]) -> Vec { assert_eq!(self.len(), v.len()); - (0..self.len()) - .map(|i| v[self.apply(i)].clone()) - .collect::>() + (0..self.len()).map(|i| v[self.apply(i)].clone()).collect() } /// Returns the composition of the permutation with itself. - pub fn square(&self) -> Permutation { + pub fn square(&self) -> Self { self * self } /// Returns the composition of the permutation with itself `exp` number of times. - pub fn pow(&self, exp: u32) -> Permutation { + pub fn pow(&self, exp: u32) -> Self { if exp == 0 { - Permutation::identity(self.len()) + Self::identity(self.len()) } else if exp == 1 { self.clone() } else if exp % 2 == 0 { @@ -105,14 +104,14 @@ impl Permutation { } } /// Returns the inverse permutation. - pub fn inv(&self) -> Permutation { + pub fn inv(&self) -> Self { let len = self.len(); let mut map = vec![0; len]; for i in 0..len { let j = self.0[i]; map[j] = i; } - Permutation(map.into_boxed_slice()) + Self(map.into_boxed_slice()) } /// The length of the permutation. /// diff --git a/src/permutations.rs b/src/permutations.rs index e1af634..ee02761 100644 --- a/src/permutations.rs +++ b/src/permutations.rs @@ -10,9 +10,9 @@ pub struct Permutations { } impl Permutations { /// Constructs the sequence of permutations of `n` elements. - pub fn new(n: usize) -> Permutations { + pub fn new(n: usize) -> Self { let len = (2..=n).product::(); - Permutations { n, len } + Self { n, len } } /// Returns the permutation at a given index. pub fn get(&self, index: usize) -> Option { @@ -68,9 +68,9 @@ pub struct Iter { next_index: usize, } impl Iter { - fn new(permutations: Permutations) -> Iter { + fn new(permutations: Permutations) -> Self { let next_index = 0; - Iter { + Self { permutations, next_index, } From 178d678569c36a184f572fc63c5ce789af563d5b Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 21 May 2023 09:44:53 -0700 Subject: [PATCH 03/10] nitpicks --- src/permutation.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/permutation.rs b/src/permutation.rs index a2098cd..b7caf3a 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -22,7 +22,7 @@ impl error::Error for TryFromError {} /// That is, all the elements in `0..len` occur exactly once in the slice. fn is_permutation(v: &[usize]) -> bool { let n = v.len(); - let mut seen = (0..n).map(|_| false).collect::>(); + let mut seen = vec![false; n]; for &e in v { if (0..n).contains(&e) { seen[e] = true; @@ -153,6 +153,7 @@ impl Permutation { } } } + impl ops::Mul for Permutation { type Output = Self; fn mul(self, other: Self) -> Self { From 6e56d255cd98dc07e490b86fdd4b0ce48762ff2c Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 21 May 2023 09:53:31 -0700 Subject: [PATCH 04/10] simplified mul --- src/permutation.rs | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index b7caf3a..1dadd77 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -157,34 +157,19 @@ impl Permutation { impl ops::Mul for Permutation { type Output = Self; fn mul(self, other: Self) -> Self { - assert_eq!(self.len(), other.len()); - Self( - (0..self.len()) - .map(|i| other.apply(self.apply(i))) - .collect(), - ) + &self * &other } } impl ops::Mul for &Permutation { type Output = Permutation; fn mul(self, other: Permutation) -> Self::Output { - assert_eq!(self.len(), other.len()); - Permutation( - (0..self.len()) - .map(|i| other.apply(self.apply(i))) - .collect(), - ) + self * &other } } impl ops::Mul<&Self> for Permutation { type Output = Self; fn mul(self, other: &Self) -> Self::Output { - assert_eq!(self.len(), other.len()); - Self( - (0..self.len()) - .map(|i| other.apply(self.apply(i))) - .collect(), - ) + &self * other } } impl ops::Mul<&Permutation> for &Permutation { From d7e15ca9e372c2018a0c5b4d1213348dae7eba56 Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 21 May 2023 10:09:41 -0700 Subject: [PATCH 05/10] nitpicks --- src/permutation.rs | 5 ++--- src/permutations.rs | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index 1dadd77..eb38965 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -107,9 +107,8 @@ impl Permutation { pub fn inv(&self) -> Self { let len = self.len(); let mut map = vec![0; len]; - for i in 0..len { - let j = self.0[i]; - map[j] = i; + for (i, j) in self.0.iter().enumerate() { + map[*j] = i; } Self(map.into_boxed_slice()) } diff --git a/src/permutations.rs b/src/permutations.rs index ee02761..d0aa95c 100644 --- a/src/permutations.rs +++ b/src/permutations.rs @@ -69,10 +69,9 @@ pub struct Iter { } impl Iter { fn new(permutations: Permutations) -> Self { - let next_index = 0; Self { permutations, - next_index, + next_index: 0, } } } From 8a324f05a1a15dbeda718fa3bf12c375b2946031 Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 21 May 2023 10:12:41 -0700 Subject: [PATCH 06/10] nitpicks --- src/permutation.rs | 17 ++++++++++++----- src/permutations.rs | 7 +++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index eb38965..b719611 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -110,7 +110,7 @@ impl Permutation { for (i, j) in self.0.iter().enumerate() { map[*j] = i; } - Self(map.into_boxed_slice()) + Self(map.into()) } /// The length of the permutation. /// @@ -159,18 +159,21 @@ impl ops::Mul for Permutation { &self * &other } } + impl ops::Mul for &Permutation { type Output = Permutation; fn mul(self, other: Permutation) -> Self::Output { self * &other } } + impl ops::Mul<&Self> for Permutation { type Output = Self; fn mul(self, other: &Self) -> Self::Output { &self * other } } + impl ops::Mul<&Permutation> for &Permutation { type Output = Permutation; fn mul(self, other: &Permutation) -> Self::Output { @@ -182,16 +185,18 @@ impl ops::Mul<&Permutation> for &Permutation { ) } } + impl TryFrom> for Permutation { type Error = TryFromError; fn try_from(v: Vec) -> Result { if is_permutation(&v) { - Ok(Self(v.into_boxed_slice())) + Ok(Self(v.into())) } else { Err(TryFromError) } } } + impl<'a> TryFrom<&'a Vec> for Permutation { type Error = TryFromError; fn try_from(v: &'a Vec) -> Result { @@ -202,6 +207,7 @@ impl<'a> TryFrom<&'a Vec> for Permutation { } } } + impl TryFrom<&[usize]> for Permutation { type Error = TryFromError; fn try_from(a: &[usize]) -> Result { @@ -212,6 +218,7 @@ impl TryFrom<&[usize]> for Permutation { } } } + impl TryFrom<&[usize; N]> for Permutation { type Error = TryFromError; fn try_from(a: &[usize; N]) -> Result { @@ -407,19 +414,19 @@ mod tests { #[test] fn test_try_from_ok_owned() { let v = vec![2, 1, 0]; - let result = Ok(Permutation(v.clone().into_boxed_slice())); + let result = Ok(Permutation(v.clone().into())); assert_eq!(result, Permutation::try_from(v)); } #[test] fn test_try_from_ok_vec_ref() { let v = vec![2, 1, 0]; - let result = Ok(Permutation(v.clone().into_boxed_slice())); + let result = Ok(Permutation(v.clone().into())); assert_eq!(result, Permutation::try_from(&v)); } #[test] fn test_try_from_ok_slice_ref() { let v = vec![2, 1, 0]; - let result = Ok(Permutation(v.clone().into_boxed_slice())); + let result = Ok(Permutation(v.clone().into())); assert_eq!(result, Permutation::try_from(&v[..])); } #[test] diff --git a/src/permutations.rs b/src/permutations.rs index d0aa95c..71841d5 100644 --- a/src/permutations.rs +++ b/src/permutations.rs @@ -8,12 +8,14 @@ pub struct Permutations { n: usize, len: usize, } + impl Permutations { /// Constructs the sequence of permutations of `n` elements. pub fn new(n: usize) -> Self { let len = (2..=n).product::(); Self { n, len } } + /// Returns the permutation at a given index. pub fn get(&self, index: usize) -> Option { if index < self.len { @@ -47,6 +49,7 @@ impl Permutations { Iter::new(self.clone()) } } + impl IntoIterator for Permutations { type Item = Permutation; type IntoIter = Iter; @@ -54,6 +57,7 @@ impl IntoIterator for Permutations { Iter::new(self) } } + impl<'a> IntoIterator for &'a Permutations { type Item = Permutation; type IntoIter = Iter; @@ -67,6 +71,7 @@ pub struct Iter { permutations: Permutations, next_index: usize, } + impl Iter { fn new(permutations: Permutations) -> Self { Self { @@ -75,6 +80,7 @@ impl Iter { } } } + impl Iterator for Iter { type Item = Permutation; fn next(&mut self) -> Option { @@ -90,6 +96,7 @@ impl Iterator for Iter { (len, Some(len)) } } + impl ExactSizeIterator for Iter {} #[cfg(test)] From 26898bbe234599397e4b73ce2a49e750e881f50c Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 25 Jun 2023 11:11:41 -0700 Subject: [PATCH 07/10] validate --- src/permutation.rs | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index b719611..9a31973 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -31,6 +31,14 @@ fn is_permutation(v: &[usize]) -> bool { seen.into_iter().all(|b| b) } +#[inline] +pub(crate) fn validate(v: &[usize]) -> Result<(), TryFromError> { + if !is_permutation(v) { + return Err(TryFromError); + } + Ok(()) +} + /// A permutation. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Permutation(Box<[usize]>); @@ -189,44 +197,32 @@ impl ops::Mul<&Permutation> for &Permutation { impl TryFrom> for Permutation { type Error = TryFromError; fn try_from(v: Vec) -> Result { - if is_permutation(&v) { - Ok(Self(v.into())) - } else { - Err(TryFromError) - } + let _ = validate(&v)?; + Ok(Self(v.into())) } } impl<'a> TryFrom<&'a Vec> for Permutation { type Error = TryFromError; fn try_from(v: &'a Vec) -> Result { - if is_permutation(v) { - Ok(Self(Box::from(&v[..]))) - } else { - Err(TryFromError) - } + let _ = validate(&v)?; + Ok(Self(v[..].into())) } } impl TryFrom<&[usize]> for Permutation { type Error = TryFromError; fn try_from(a: &[usize]) -> Result { - if is_permutation(a) { - Ok(Self(Box::from(a))) - } else { - Err(TryFromError) - } + let _ = validate(&a)?; + Ok(Self(a.into())) } } impl TryFrom<&[usize; N]> for Permutation { type Error = TryFromError; fn try_from(a: &[usize; N]) -> Result { - if is_permutation(a) { - Ok(Self(Box::from(&a[..]))) - } else { - Err(TryFromError) - } + let _ = validate(a.as_slice())?; + Ok(Self(a[..].into())) } } From 0fa8baa0fbcc93b781bdfb75e664db59291eddda Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Sun, 25 Jun 2023 11:19:49 -0700 Subject: [PATCH 08/10] nitpicks --- src/permutation.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index 9a31973..8e91389 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -1,12 +1,7 @@ -use std::error; -use std::fmt; -use std::ops; +use std::{error, fmt, ops}; #[cfg(feature = "random")] -use rand::Rng; - -#[cfg(feature = "random")] -use crate::Permutations; +use {crate::Permutations, rand::Rng}; #[derive(Clone, Copy, Debug, PartialEq)] pub struct TryFromError; From 7f46abf2d1b5a4ee03440dab4ab568a5166d1ecf Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Fri, 7 Jul 2023 14:59:25 -0700 Subject: [PATCH 09/10] added is_identity function --- src/permutation.rs | 13 ++++++++++--- src/permutations.rs | 31 +++++++++++++++---------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index 8e91389..b7dfc5c 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -43,6 +43,12 @@ impl Permutation { pub fn identity(n: usize) -> Self { Self((0..n).collect()) } + + /// Checks if permutation is identity + pub fn is_identity(&self) -> bool { + (0..self.len()).eq(self.0.iter().cloned()) + } + /// Returns the permutation of n elements which rotates r steps to the left. pub fn rotation_left(n: usize, r: usize) -> Self { Self((0..n).map(|i| (i + r) % n).collect()) @@ -156,7 +162,7 @@ impl Permutation { } } -impl ops::Mul for Permutation { +impl ops::Mul for Permutation { type Output = Self; fn mul(self, other: Self) -> Self { &self * &other @@ -172,12 +178,12 @@ impl ops::Mul for &Permutation { impl ops::Mul<&Self> for Permutation { type Output = Self; - fn mul(self, other: &Self) -> Self::Output { + fn mul(self, other: &Self) -> Self { &self * other } } -impl ops::Mul<&Permutation> for &Permutation { +impl ops::Mul for &Permutation { type Output = Permutation; fn mul(self, other: &Permutation) -> Self::Output { assert_eq!(self.len(), other.len()); @@ -249,6 +255,7 @@ mod tests { fn test_identity() { let id = Permutation::identity(3); assert_eq!(Permutation(Box::new([0, 1, 2])), id); + assert!(id.is_identity()); } #[test] diff --git a/src/permutations.rs b/src/permutations.rs index 71841d5..576fc19 100644 --- a/src/permutations.rs +++ b/src/permutations.rs @@ -18,23 +18,22 @@ impl Permutations { /// Returns the permutation at a given index. pub fn get(&self, index: usize) -> Option { - if index < self.len { - let mut v = Vec::new(); - let mut es = (0..self.n).collect::>(); - let mut divisor = self.len; - let mut k = self.n; - let mut i = index; - while k > 0 { - divisor /= k; - let j = i / divisor; - v.push(es.remove(j)); - i %= divisor; - k -= 1; - } - Some(Permutation::try_from(v).unwrap()) - } else { - None + if index >= self.len { + return None; + } + let mut v = vec![]; + let mut es = (0..self.n).collect::>(); + let mut divisor = self.len; + let mut k = self.n; + let mut i = index; + while k > 0 { + divisor /= k; + let j = i / divisor; + v.push(es.remove(j)); + i %= divisor; + k -= 1; } + Some(Permutation::try_from(v).unwrap()) } /// Returns the number of permutations in the sequence. /// From 534ff0de3c3a5b60ec0b04a34aee2ef555aadbe0 Mon Sep 17 00:00:00 2001 From: adamnemecek Date: Fri, 7 Jul 2023 15:06:19 -0700 Subject: [PATCH 10/10] moved error --- src/permutation.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/permutation.rs b/src/permutation.rs index b7dfc5c..826df2e 100644 --- a/src/permutation.rs +++ b/src/permutation.rs @@ -26,14 +26,6 @@ fn is_permutation(v: &[usize]) -> bool { seen.into_iter().all(|b| b) } -#[inline] -pub(crate) fn validate(v: &[usize]) -> Result<(), TryFromError> { - if !is_permutation(v) { - return Err(TryFromError); - } - Ok(()) -} - /// A permutation. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Permutation(Box<[usize]>); @@ -195,6 +187,14 @@ impl ops::Mul for &Permutation { } } +#[inline] +fn validate(v: &[usize]) -> Result<(), TryFromError> { + if !is_permutation(v) { + return Err(TryFromError); + } + Ok(()) +} + impl TryFrom> for Permutation { type Error = TryFromError; fn try_from(v: Vec) -> Result {