24: Add WIP solution for Rust track exercise "Sum Of Multiples".
[?]
Aaw9nJhsNmfzFih9mKyNw9mV8CgERXJkRa1kK1Kx3LQH
Sep 1, 2021, 11:33 AM
SPUEEQZQFZDVOLZTAXLRHXPCQ3JWN32O7YCND24XVCHYIDNNT4QQCDependencies
- [2]
QK6XE5XF13: Add Rust track exercises "Beer Song", "Proverb", "Difference Of Squares", "Sum Of Multiples", "Grains", "Prime Factors", "Armstrong Numbers" and "Reverse String".
Change contents
- replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 5
assert_eq!(0, sum_of_multiples(1, &[3, 5]))assert_eq!(0, sum_of_multiples(1, &[3, 5])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 11
assert_eq!(3, sum_of_multiples(4, &[3, 5]))assert_eq!(3, sum_of_multiples(4, &[3, 5])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 17
assert_eq!(9, sum_of_multiples(7, &[3]))assert_eq!(9, sum_of_multiples(7, &[3])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 23
assert_eq!(23, sum_of_multiples(10, &[3, 5]))assert_eq!(23, sum_of_multiples(10, &[3, 5])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 29
assert_eq!(2318, sum_of_multiples(100, &[3, 5]))assert_eq!(2318, sum_of_multiples(100, &[3, 5])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 35
assert_eq!(233_168, sum_of_multiples(1000, &[3, 5]))assert_eq!(233_168, sum_of_multiples(1000, &[3, 5])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 41
assert_eq!(51, sum_of_multiples(20, &[7, 13, 17]))assert_eq!(51, sum_of_multiples(20, &[7, 13, 17])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 47
assert_eq!(30, sum_of_multiples(15, &[4, 6]))assert_eq!(30, sum_of_multiples(15, &[4, 6])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 53
assert_eq!(4419, sum_of_multiples(150, &[5, 6, 8]))assert_eq!(4419, sum_of_multiples(150, &[5, 6, 8])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 59
assert_eq!(275, sum_of_multiples(51, &[5, 25]))assert_eq!(275, sum_of_multiples(51, &[5, 25])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 65
assert_eq!(2_203_160, sum_of_multiples(10_000, &[43, 47]))assert_eq!(2_203_160, sum_of_multiples(10_000, &[43, 47])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 71
assert_eq!(4950, sum_of_multiples(100, &[1]))assert_eq!(4950, sum_of_multiples(100, &[1])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 77
assert_eq!(0, sum_of_multiples(10_000, &[]))assert_eq!(0, sum_of_multiples(10_000, &[])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 83
assert_eq!(0, sum_of_multiples(1, &[0]))assert_eq!(0, sum_of_multiples(1, &[0])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 89
assert_eq!(3, sum_of_multiples(4, &[3, 0]))assert_eq!(3, sum_of_multiples(4, &[3, 0])) - replacement in rust/sum-of-multiples/tests/sum-of-multiples.rs at line 95
assert_eq!(39_614_537, sum_of_multiples(10_000, &[2, 3, 5, 7, 11]))assert_eq!(39_614_537, sum_of_multiples(10_000, &[2, 3, 5, 7, 11])) - edit in rust/sum-of-multiples/src/lib.rs at line 1
mod error_a {use std::{error, fmt};#[derive(Debug)]pub enum CreationError<A> {SubsetBiggerThanSet { set: Vec<A>, subset_size: usize },}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> error::Error for CreationError<A> {}}mod combinations {use crate::error_a::CreationError;#[derive(PartialEq)]enum State {A,B,C,D,E,}pub struct CombinationsWithoutReplacement<'a, A>whereA: Clone,{set: &'a [A],subset_indices: Vec<usize>,index: usize,state: State,}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,})}}// 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() => {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(),)}}}// 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;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;}}// 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;} else {// Endself.state = State::E;}}}}impl<A> Iterator for CombinationsWithoutReplacement<'_, A>whereA: Clone,{type Item = Vec<A>;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(),_ => (),}}self.next()}}}}}mod num_traits {pub trait Unsigned {}impl Unsigned for u32 {}}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> Iterator for UnsignedMultiples<A>whereA: core::ops::AddAssign + core::ops::Sub<Output = A> + Copy + PartialOrd + Unsigned,{type Item = A;fn next(&mut self) -> Option<Self::Item> {if self.out < self.limit {self.out += self.factor;Some(self.out - self.factor)} else {None}}}}use crate::{combinations::CombinationsWithoutReplacement, error_a::CreationError,multiples::UnsignedMultiples,};fn sum_of_multiples_go(factors: &[u32], limit: u32) -> Result<u32, CreationError<u32>> {(1..=factors.len()).try_fold(0,|accumulator_a, subset_size| -> Result<u32, CreationError<u32>> {Ok(if subset_size & 1 == 1 {accumulator_a+ CombinationsWithoutReplacement::new(factors, subset_size)?.fold(0,|accumulator_b, combination| {accumulator_b+ UnsignedMultiples::new(combination.iter().product(), limit).sum::<u32>()},)} else {accumulator_a- CombinationsWithoutReplacement::new(factors, subset_size)?.fold(0,|accumulator_b, combination| {accumulator_b+ UnsignedMultiples::new(combination.iter().product(), limit).sum::<u32>()},)})},)} - replacement in rust/sum-of-multiples/src/lib.rs at line 265
unimplemented!("Sum the multiples of all of {:?} which are less than {}",factors,limit)let factors = factors.iter().copied().filter(|factor| *factor != 0).collect::<Vec<u32>>();if factors.is_empty() {0} else {sum_of_multiples_go(&factors, limit).unwrap()}