diff --git a/multiply_strings/src/main.rs b/multiply_strings/src/main.rs index d67a7b3..6210ac7 100644 --- a/multiply_strings/src/main.rs +++ b/multiply_strings/src/main.rs @@ -1,73 +1,81 @@ -pub fn multiply(num1: String, num2: String) -> String { - // +struct S(); - let mut out: Vec = (0..(num1.len() + num2.len())) - .into_iter() - .map(|_| 0) - .collect(); +impl S { + pub fn multiply(num1: String, num2: String) -> String { + let l1 = num1.len(); + let l2 = num2.len(); + // get the longest one as num1 + let (num1, num2) = if l1 < l2 { (num2, num1) } else { (num1, num2) }; - let l1 = num1.len(); - let l2 = num2.len(); - - // get the longest one as num1 - let (num1, num2) = if l1 < l2 { (num2, num1) } else { (num1, num2) }; - - for (i2, d2) in num2.chars().rev().enumerate() { - let mut mcarry = 0; - let mut tmp: Vec = (0..i2).into_iter().map(|_| 0).collect(); - let d2 = d2.to_digit(10).unwrap(); - for d1 in num1.chars().rev() { - let d1 = d1.to_digit(10).unwrap(); - let p = (d1 * d2) + mcarry; - mcarry = p / 10; - let p = p % 10; - tmp.push(p); + if l1 == 0 || l2 == 0 { + return "0".to_string(); } - if mcarry > 0 { - tmp.push(mcarry); + let tsize = l1.max(l2); + + let mut out: Vec = (0..(num1.len() + num2.len())) + .into_iter() + .map(|_| 0) + .collect(); + for (i2, d2) in num2.chars().rev().enumerate() { + let mut mcarry = 0; + let mut tmp: Vec = (0..i2).into_iter().map(|_| 0).collect(); + tmp.reserve(tsize - i2); + let d2 = d2.to_digit(10).unwrap(); + for d1 in num1.chars().rev() { + let d1 = d1.to_digit(10).unwrap(); + let p = (d1 * d2) + mcarry; + mcarry = p / 10; + let p = p % 10; + tmp.push(p); + } + if mcarry > 0 { + tmp.push(mcarry); + } + Self::merge(&mut out, &tmp); } - merge(&mut out, &tmp); - } - while let Some(last) = out.last() { - if *last == 0 { - let len = out.len() - 1; - out = out[0..len].to_vec(); + + let s: String = out + .into_iter() + .rev() + .skip_while(|d| *d == 0) + // SAFETY: the input is guaranteed to be valid + .map(|d| unsafe { char::from_digit(d, 10).unwrap_unchecked() }) + .collect(); + + if s.is_empty() { + "0".to_string() } else { - break; + s } } - if out.is_empty() { - out.push(0); - } - out.iter().rev().map(|d| d.to_string()).collect() -} + fn merge(out: &mut [u32], rhs: &[u32]) { + // + let mut acarry = 0; + let len = rhs.len(); + (0..len).for_each(|i| { + let oi = out[i]; + let ri = rhs[i]; + let s = oi + ri + acarry; + acarry = s / 10; + let s = s % 10; + out[i] = s; + }); -fn merge(out: &mut [u32], rhs: &[u32]) { - // - let mut acarry = 0; - let len = rhs.len(); - (0..len).for_each(|i| { - let oi = out[i]; - let ri = rhs[i]; - let s = oi + ri + acarry; - acarry = s / 10; - let s = s % 10; - out[i] = s; - }); - if acarry > 0 { - out[len] = acarry; + if acarry > 0 { + out[len] = acarry; + } } } fn main() { - dbg!(multiply("2".to_string(), "4".to_string())); - dbg!(multiply("27".to_string(), "49".to_string())); - dbg!(multiply( + dbg!(S::multiply("2".to_string(), "4".to_string())); + dbg!(S::multiply("27".to_string(), "49".to_string())); + dbg!(S::multiply( "20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" .to_string(), "4000000000000000000000000000000000000000000000000000000000000000".to_string() )); - dbg!(multiply("0".to_string(), "8".to_string())); + dbg!(S::multiply("".to_string(), "88".to_string())); }