35: Refactor WIP solution for Rust track exercise "Sum of Multiples".
[?]
Aaw9nJhsNmfzFih9mKyNw9mV8CgERXJkRa1kK1Kx3LQH
Oct 9, 2021, 12:45 PM
KOISBSJ3KKEP44EXD6CC3NVTTQLLOBZDONMHTVLGOSTDXUD6SJTQCDependencies
- [2]
SPUEEQZQ24: Add WIP solution for Rust track exercise "Sum Of Multiples". - [3]
YGJVWTKA34: Improve solution for Rust track exercise "Nth Prime". - [4]
JZN2AQ3E10: Add Rust track exercise "nth-prime". - [5]
IXMBS6ZP29: Improve solution for Rust track exercise "Nth Prime". - [6]
ZSKHCSQ530: Fix regression introduced in solution for Rust track exercise "Nth Prime". - [7]
ERYD4CD711: Add solution for Rust track exercise "Nth Prime". - [8]
VH5OFL5532: Improve solution for Rust track exercise "Nth Prime". - [9]
MXKH26RW26: Refactor solution for Rust track exercise "Sum Of Multiples". - [10]
UTP7D53Q12: Improve solution for Rust track exercise "Nth Prime". - [11]
QK6XE5XF13: Add Rust track exercises "Beer Song", "Proverb", "Difference Of Squares", "Sum Of Multiples", "Grains", "Prime Factors", "Armstrong Numbers" and "Reverse String". - [12]
KWE5K6XL23: Fix panix on input `12` for solution for Rust track exercise "Nth Prime". - [13]
XDEY7SNL31: Improve solution for Rust track exercise "Raindrops".
Change contents
- replacement in rust/sum-of-multiples/src/lib.rs at line 1
mod error_a {use std::{error, fmt};//! Finds the sum of all the unique multiples of particular numbers up to but not including a specified number.use std::{error, fmt}; - replacement in rust/sum-of-multiples/src/lib.rs at line 4
#[derive(Debug)]pub enum CreationError<A> {SubsetBiggerThanSet { set: Vec<A>, subset_size: usize },}#[derive(Debug)]/// Possible error from struct creation.enum CreationError<A> {SubsetBiggerThanSet { set: Vec<A>, subset_size: usize },} - replacement in rust/sum-of-multiples/src/lib.rs at line 10
impl<A: std::fmt::Debug> fmt::Display for CreationError<A> {fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {match self {CreationError::SubsetBiggerThanSet { set, subset_size } => write!(f,"Subset can't be bigger than set.\nset: {:?}\nsubset_size: {:?}",set, subset_size),}impl<A: std::fmt::Debug> fmt::Display for CreationError<A> {fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {match self {CreationError::SubsetBiggerThanSet { set, subset_size } => write!(f,"Subset can't be bigger than set.\nset: {:?}\nsubset_size: {:?}",set, subset_size), - edit in rust/sum-of-multiples/src/lib.rs at line 20
impl<A: std::fmt::Debug> error::Error for CreationError<A> {} - replacement in rust/sum-of-multiples/src/lib.rs at line 22
mod combinations {use crate::error_a::CreationError;impl<A: std::fmt::Debug> error::Error for CreationError<A> {} - replacement in rust/sum-of-multiples/src/lib.rs at line 24
#[derive(PartialEq)]enum State {A,B,C,D,E,}#[derive(PartialEq)]/// Represents the possible states of a state machine.enum State {A,B,C,D,E,} - replacement in rust/sum-of-multiples/src/lib.rs at line 34
pub struct CombinationsWithoutReplacement<'a, A>whereA: Clone,{set: &'a [A],subset_indices: Vec<usize>,index: usize,state: State,}/// Generates combinations of elements of a set without replacement/repetition of the elements./// Implements the [Revolving Door algorithm](http://math0.wvstateu.edu/~baker/cs405/code/RevolvingDoor.html).struct CombinationsWithoutReplacement<'a, A>whereA: Clone,{set: &'a [A],subset_indices: Vec<usize>,index: usize,state: State,} - replacement in rust/sum-of-multiples/src/lib.rs at line 46
impl<A> CombinationsWithoutReplacement<'_, A>whereA: Clone,{// R1: Initialisepub fn new(set: &[A],subset_size: usize,) -> Result<CombinationsWithoutReplacement<A>, CreationError<A>> {if set.len() < subset_size {Err(CreationError::SubsetBiggerThanSet {set: set.to_owned(),subset_size,})} else {Ok(CombinationsWithoutReplacement {set,subset_indices: {let mut a: Vec<usize> = Vec::with_capacity(subset_size + 1);for b in 0..subset_size {a.push(b);}a.push(set.len());a},index: 0,state: State::A,})}impl<A> CombinationsWithoutReplacement<'_, A>whereA: Clone,{// R1: Initialise/// # Arguments////// * `set`: Set to generate combinations of./// * `subset_size`: Size of subsets containing the combinations to output.fn new(set: &[A],subset_size: usize,) -> Result<CombinationsWithoutReplacement<A>, CreationError<A>> {if set.len() < subset_size {Err(CreationError::SubsetBiggerThanSet {set: set.to_owned(),subset_size,})} else {Ok(CombinationsWithoutReplacement {set,subset_indices: {let mut a: Vec<usize> = Vec::with_capacity(subset_size + 1);for b in 0..subset_size {a.push(b);}a.push(set.len());a},index: 0,state: State::A,}) - edit in rust/sum-of-multiples/src/lib.rs at line 79
} - replacement in rust/sum-of-multiples/src/lib.rs at line 81
// R2: State::Afn visit(&mut self) -> Option<Vec<A>> {match self.subset_indices.len() - 1 {0 => Some(vec![]),1 => {self.index += 1;if self.index > self.set.len() {self.state = State::E;None} else {Some(vec![self.set[self.index - 1].clone()])}}index if index == self.set.len() => {// R2: State::Afn visit(&mut self) -> Option<Vec<A>> {match self.subset_indices.len() - 1 {0 => Some(vec![]),1 => {self.index += 1;if self.index > self.set.len() { - replacement in rust/sum-of-multiples/src/lib.rs at line 89
Some(self.set.to_vec())}_ => {self.state = State::B;Some(self.subset_indices[0..self.subset_indices.len() - 1].iter().map(|index| self.set[*index].clone()).collect(),)None} else {Some(vec![self.set[self.index - 1].clone()]) - edit in rust/sum-of-multiples/src/lib.rs at line 93
}index if index == self.set.len() => {self.state = State::E;Some(self.set.to_vec())}_ => {self.state = State::B;Some(self.subset_indices[0..self.subset_indices.len() - 1].iter().map(|&index| self.set[index].clone()).collect(),) - edit in rust/sum-of-multiples/src/lib.rs at line 108
} - replacement in rust/sum-of-multiples/src/lib.rs at line 110
// R3: State::Bfn easy_cases(&mut self) {if (self.subset_indices.len() - 1) & 1 == 1 {if self.subset_indices[0] + 1 < self.subset_indices[1] {self.subset_indices[0] += 1;self.state = State::A;} else {self.index = 1;self.state = State::C;}} else if self.subset_indices[0] > 0 {self.subset_indices[0] -= 1;// R3: State::Bfn easy_cases(&mut self) {if (self.subset_indices.len() - 1) & 1 == 1 {if self.subset_indices[0] + 1 < self.subset_indices[1] {self.subset_indices[0] += 1; - replacement in rust/sum-of-multiples/src/lib.rs at line 118
self.state = State::D;self.state = State::C; - edit in rust/sum-of-multiples/src/lib.rs at line 120
} else if self.subset_indices[0] > 0 {self.subset_indices[0] -= 1;self.state = State::A;} else {self.index = 1;self.state = State::D; - edit in rust/sum-of-multiples/src/lib.rs at line 127
} - replacement in rust/sum-of-multiples/src/lib.rs at line 129
// R4: State::Cfn try_to_decrease_at_index(&mut self) {if self.subset_indices[self.index] > self.index {self.subset_indices[self.index] = self.subset_indices[self.index - 1];self.subset_indices[self.index - 1] = self.index - 1;self.state = State::A;} else {self.index += 1;self.state = State::D;}// R4: State::Cfn try_to_decrease_at_index(&mut self) {if self.subset_indices[self.index] > self.index {self.subset_indices[self.index] = self.subset_indices[self.index - 1];self.subset_indices[self.index - 1] = self.index - 1;self.state = State::A;} else {self.index += 1;self.state = State::D; - edit in rust/sum-of-multiples/src/lib.rs at line 139
} - replacement in rust/sum-of-multiples/src/lib.rs at line 141
// R5: State::Dfn try_to_increase_at_index(&mut self) {if self.subset_indices[self.index] + 1 < self.subset_indices[self.index + 1] {self.subset_indices[self.index - 1] = self.subset_indices[self.index];self.subset_indices[self.index] += 1;self.state = State::A;// R5: State::Dfn try_to_increase_at_index(&mut self) {if self.subset_indices[self.index] + 1 < self.subset_indices[self.index + 1] {self.subset_indices[self.index - 1] = self.subset_indices[self.index];self.subset_indices[self.index] += 1;self.state = State::A;} else {self.index += 1;if self.index < (self.subset_indices.len() - 1) {self.state = State::C; - replacement in rust/sum-of-multiples/src/lib.rs at line 152
self.index += 1;if self.index < (self.subset_indices.len() - 1) {self.state = State::C;} else {// Endself.state = State::E;}// Endself.state = State::E; - edit in rust/sum-of-multiples/src/lib.rs at line 157
} - replacement in rust/sum-of-multiples/src/lib.rs at line 159
impl<A> Iterator for CombinationsWithoutReplacement<'_, A>whereA: Clone,{type Item = Vec<A>;impl<A> Iterator for CombinationsWithoutReplacement<'_, A>whereA: Clone,{type Item = Vec<A>; - replacement in rust/sum-of-multiples/src/lib.rs at line 165
fn next(&mut self) -> Option<Self::Item> {match self.state {State::A => self.visit(),State::E => None,_ => {while self.state != State::A && self.state != State::E {match self.state {State::B => self.easy_cases(),State::C => self.try_to_decrease_at_index(),State::D => self.try_to_increase_at_index(),_ => (),}fn next(&mut self) -> Option<Self::Item> {match self.state {State::A => self.visit(),State::E => None,_ => {while self.state != State::A && self.state != State::E {match self.state {State::B => self.easy_cases(),State::C => self.try_to_decrease_at_index(),State::D => self.try_to_increase_at_index(),_ => (), - edit in rust/sum-of-multiples/src/lib.rs at line 177
self.next() - edit in rust/sum-of-multiples/src/lib.rs at line 178
self.next() - replacement in rust/sum-of-multiples/src/lib.rs at line 184
mod num_traits {pub trait Unsigned {}trait Unsigned {}impl Unsigned for u32 {} - replacement in rust/sum-of-multiples/src/lib.rs at line 188
impl Unsigned for u32 {}#[derive(Debug)]/// Returns the multiples of a number up to but not including a specified limit.struct UnsignedMultiples<A>whereA: Copy + Unsigned,{factor: A,limit: A,out: A, - replacement in rust/sum-of-multiples/src/lib.rs at line 199
mod multiples {use crate::num_traits::Unsigned;#[derive(Debug)]pub struct UnsignedMultiples<A>whereA: Copy + Unsigned,{factor: A,limit: A,out: A,}impl<A> UnsignedMultiples<A>whereA: Copy + Unsigned,{pub fn new(factor: A, limit: A) -> UnsignedMultiples<A> {UnsignedMultiples {factor,limit,out: factor,}impl<A> UnsignedMultiples<A>whereA: Copy + Unsigned,{/// # Arguments////// * `factor`: Number to generate multiples of./// * `limit`: Number at which no more multiples will be generated.fn new(factor: A, limit: A) -> UnsignedMultiples<A> {UnsignedMultiples {factor,limit,out: factor, - edit in rust/sum-of-multiples/src/lib.rs at line 214
} - replacement in rust/sum-of-multiples/src/lib.rs at line 216
impl<A> Iterator for UnsignedMultiples<A>whereA: core::ops::AddAssign + core::ops::Sub<Output = A> + Copy + PartialOrd + Unsigned,{type Item = A;impl<A> Iterator for UnsignedMultiples<A>whereA: core::ops::AddAssign + core::ops::Sub<Output = A> + Copy + PartialOrd + Unsigned,{type Item = A; - replacement in rust/sum-of-multiples/src/lib.rs at line 222
fn next(&mut self) -> Option<Self::Item> {if self.out < self.limit {self.out += self.factor;Some(self.out - self.factor)} else {None}fn next(&mut self) -> Option<Self::Item> {if self.out < self.limit {let out = self.out;self.out += self.factor;Some(out)} else {None - edit in rust/sum-of-multiples/src/lib.rs at line 232
use crate::{combinations::CombinationsWithoutReplacement, error_a::CreationError,multiples::UnsignedMultiples,}; - edit in rust/sum-of-multiples/src/lib.rs at line 251
/// Finds the sum of all the unique multiples of particular numbers up to but not including a specified number. - replacement in rust/sum-of-multiples/src/lib.rs at line 253
let factors = factorslet mut factors = factors.to_vec();factors.sort_unstable();let mut done: Vec<u32> = Vec::with_capacity(factors.len());let mut out: Vec<u32> = Vec::with_capacity(factors.len());factors - replacement in rust/sum-of-multiples/src/lib.rs at line 260
.filter(|factor| *factor != 0).collect::<Vec<u32>>();if factors.is_empty() {.filter(|&factor| factor != 0).for_each(|factor| {if done.iter().all(|&done_factor| factor % done_factor != 0) {out.push(factor);}done.push(factor);});if out.is_empty() { - replacement in rust/sum-of-multiples/src/lib.rs at line 270
sum_of_multiples_go(&factors, limit).unwrap()sum_of_multiples_go(&out, limit).unwrap() - edit in rust/nth-prime/src/lib.rs at line 1
use std::convert::TryInto; - edit in rust/nth-prime/src/lib.rs at line 9
TODO:* Use bases 2, 3, 5, 7 for wheel factorisation.* Implement segmented sieve algorithm.* Multi-thread with Mutex and lazy_static.* Use bitbox from bitvec for bit compression. - edit in rust/nth-prime/src/lib.rs at line 16
- replacement in rust/nth-prime/src/lib.rs at line 31
// Approximated size of the list required using the inverse of an approximation of the prime-counting function, halved (as we're only interested in odd numbers).let list_size = (corrected_n * (corrected_n * corrected_n.ln()).ln() / 2.0) as usize + 1;// Approximated size of the list required using the inverse of an approximation of the prime-counting function, halved (as we're only interested in odd numbers). Lossy cast.let list_size = (corrected_n * (corrected_n * corrected_n.ln()).ln() / 2.0).ceil() as usize; - replacement in rust/nth-prime/src/lib.rs at line 39
(list_size as f64).sqrt() as usize + 1,// Lossy cast.(list_size as f64).sqrt().ceil() as usize, - replacement in rust/nth-prime/src/lib.rs at line 49
// Might panic if values greater than u32::MAX are cast.return (index * 2 + 1) as u32;// Might panic if values greater than u32::MAX are converted.return (index * 2 + 1).try_into().unwrap(); - replacement in rust/nth-prime/src/lib.rs at line 61
// Might panic if values greater than u32::MAX are cast.return (index * 2 + 1) as u32;// Might panic if values greater than u32::MAX are converted.return (index * 2 + 1).try_into().unwrap();