Решение на Bigint от Ралица Добрева
Резултати
- 15 точки от тестове
- 0 бонус точки
- 15 точки общо
- 15 успешни тест(а)
- 0 неуспешни тест(а)
Код
#[derive(Debug, PartialEq, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
pub fn new() -> Self {
return Bigint {
sign: 1i8,
digits: Vec::new(),
};
}
fn from_components(digits: Vec<u8>, sign: i8) -> Self {
let mut final_digit = digits;
let mut deleteNumber = 0;
for digit in final_digit.iter() {
if digit == &0u8 {
deleteNumber += 1;
} else {
break;
}
}
for _ in 0..deleteNumber {
final_digit.remove(0);
}
if final_digit.is_empty() {
return Bigint::new();
}
return Bigint {
sign: sign,
digits: final_digit,
};
}
pub fn to_string(&self) -> String {
let mut res = String::new();
for ch in &self.digits {
res.push_str(&ch.to_string());
}
return res;
}
pub fn is_positive(&self) -> bool {
if self.digits.is_empty() {
return false;
}
return self.sign == 1i8;
}
pub fn is_negative(&self) -> bool {
if self.digits.is_empty() {
return false;
}
return self.sign == -1i8;
}
}
use std::str::FromStr;
#[derive(Debug)]
pub struct ParseError;
impl FromStr for Bigint {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut digits: Vec<u8> = Vec::new();
let mut sign = 1i8;
for (i, c) in s.chars().enumerate() {
if c == '-' && i == 0 {
sign = -1i8;
continue;
} else if c == '+' && i == 0 {
continue;
}
if c.is_numeric() {
digits.push(c.to_string().parse::<u8>().unwrap());
} else {
return Err(ParseError);
}
}
return Ok(Bigint::from_components(digits, sign));
}
}
use std::cmp::Ordering;
impl PartialOrd for Bigint {
fn partial_cmp(&self, other: &Bigint) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Bigint {
fn cmp(&self, other: &Bigint) -> Ordering {
if self.sign != other.sign {
return (self.sign).cmp(&other.sign);
} else if self.to_string() == other.to_string() {
return Ordering::Equal;
}
if self.sign == 1i8 {
if isSmaller(&self.to_string(), &other.to_string()) {
return Ordering::Less;
} else {
return Ordering::Greater;
}
} else if isSmaller(&self.to_string(), &other.to_string()) {
return Ordering::Greater;
} else {
return Ordering::Less;
}
}
}
use std::ops::{Add, Sub};
impl Add for Bigint {
type Output = Bigint;
fn add(self, other: Self) -> Self {
let mut sign = 1i8;
if self.sign == other.sign && self.sign == -1i8 {
sign = -1i8;
} else if self.sign != other.sign {
if self.sign == 1i8 {
let n = Bigint {
sign: 1i8,
digits: other.digits,
};
return self - n;
} else {
return self - other;
}
}
let mut num1 = self.to_string();
let mut num2 = other.to_string();
if num1.len() > num2.len() {
num1 = num2;
num2 = self.to_string();
}
let mut res = String::new();
let mut n1 = num1.len();
let mut n2 = num2.len();
num1 = num1.chars().rev().collect::<String>();
num2 = num2.chars().rev().collect::<String>();
let mut carry = 0;
for i in 0..n1 {
let mut sum = num1.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0)
+ num2.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0)
+ carry;
res.push_str(&(sum % 10).to_string());
carry = sum / 10;
}
for i in n1..n2 {
let mut sum = num2.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0) + carry;
res.push_str(&(sum % 10).to_string());
carry = sum / 10;
}
if carry != 0u32 {
res.push_str(&carry.to_string());
}
res = res.chars().rev().collect::<String>();
let mut sign_string = String::new();
if sign == 1i8 {
sign_string = "+".to_string();
} else {
sign_string = "-".to_string();
}
sign_string.push_str(&res);
res = sign_string;
return Bigint::from_str(&res).unwrap();
}
}
impl Sub for Bigint {
type Output = Bigint;
fn sub(self, other: Self) -> Self {
let mut sign = 1i8;
let mut num1 = self.to_string();
let mut num2 = other.to_string();
if self.sign == other.sign && self.sign == -1i8 {
let n = Bigint {
sign: 1i8,
digits: other.digits,
};
return self + n;
} else if self.sign != other.sign {
if self.sign == 1i8 {
let n = Bigint {
sign: 1i8,
digits: other.digits,
};
return self + n;
} else {
let n = Bigint {
sign: -1i8,
digits: self.digits,
};
return other + n;
}
}
if isSmaller(&num1, &num2) {
sign = -1i8;
num1 = num2;
num2 = self.to_string();
}
let mut res = String::new();
let mut n1 = num1.len();
let mut n2 = num2.len();
num1 = num1.chars().rev().collect::<String>();
num2 = num2.chars().rev().collect::<String>();
let mut carry = 0;
for i in 0..n2 {
let mut sub = num1.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0) as i32
- num2.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0) as i32
- carry as i32;
if sub < 0 {
sub = sub + 10;
carry = 1;
} else {
carry = 0;
}
res.push_str(&sub.to_string());
}
for i in n2..n1 {
let mut sub =
num1.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0) as i32 - carry as i32;
if sub < 0 {
sub = sub + 10;
carry = 1;
} else {
carry = 0;
}
res.push_str(&sub.to_string());
}
res = res.chars().rev().collect::<String>();
let mut sign_string = String::new();
if sign == 1i8 {
sign_string = "+".to_string();
} else {
sign_string = "-".to_string();
}
sign_string.push_str(&res);
res = sign_string;
return Bigint::from_str(&res).unwrap();
}
}
fn isSmaller(num1: &str, num2: &str) -> bool {
let l1 = num1.len();
let l2 = num2.len();
if l1 < l2 {
return true;
}
if l2 < l1 {
return false;
}
return num1 < num2;
}
fn bigint(s: &str) -> Bigint {
Bigint::from_str(s).unwrap()
}
fn main() {}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20201127-2274206-77iujz/solution) warning: value assigned to `sign_string` is never read --> src/lib.rs:187:13 | 187 | let mut sign_string = String::new(); | ^^^^^^^^^^^^^^^ | = note: `#[warn(unused_assignments)]` on by default = help: maybe it is overwritten before being read? warning: value assigned to `sign_string` is never read --> src/lib.rs:277:13 | 277 | let mut sign_string = String::new(); | ^^^^^^^^^^^^^^^ | = help: maybe it is overwritten before being read? warning: variable does not need to be mutable --> src/lib.rs:157:13 | 157 | let mut n1 = num1.len(); | ----^^ | | | help: remove this `mut` | = note: `#[warn(unused_mut)]` on by default warning: variable does not need to be mutable --> src/lib.rs:158:13 | 158 | let mut n2 = num2.len(); | ----^^ | | | help: remove this `mut` warning: variable does not need to be mutable --> src/lib.rs:166:17 | 166 | let mut sum = num1.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0) | ----^^^ | | | help: remove this `mut` warning: variable does not need to be mutable --> src/lib.rs:175:17 | 175 | let mut sum = num2.chars().nth(i).unwrap_or('0').to_digit(10).unwrap_or(0) + carry; | ----^^^ | | | help: remove this `mut` warning: variable does not need to be mutable --> src/lib.rs:239:13 | 239 | let mut n1 = num1.len(); | ----^^ | | | help: remove this `mut` warning: variable does not need to be mutable --> src/lib.rs:240:13 | 240 | let mut n2 = num2.len(); | ----^^ | | | help: remove this `mut` warning: function is never used: `bigint` --> src/lib.rs:306:4 | 306 | fn bigint(s: &str) -> Bigint { | ^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: function is never used: `main` --> src/lib.rs:310:4 | 310 | fn main() {} | ^^^^ warning: variable `deleteNumber` should have a snake case name --> src/lib.rs:17:17 | 17 | let mut deleteNumber = 0; | ^^^^^^^^^^^^ help: convert the identifier to snake case: `delete_number` | = note: `#[warn(non_snake_case)]` on by default warning: function `isSmaller` should have a snake case name --> src/lib.rs:291:4 | 291 | fn isSmaller(num1: &str, num2: &str) -> bool { | ^^^^^^^^^ help: convert the identifier to snake case: `is_smaller` warning: 12 warnings emitted Finished test [unoptimized + debuginfo] target(s) in 1.74s Running target/debug/deps/solution_test-589a43f0f4b10ca3 running 15 tests test solution_test::test_bigint_construction ... ok test solution_test::test_bigint_nonzero_sign ... ok test solution_test::test_bigint_zero_sign ... ok test solution_test::test_comparison ... ok test solution_test::test_invalid_string ... ok test solution_test::test_neutralization ... ok test solution_test::test_parsing_with_and_without_sign ... ok test solution_test::test_parsing_with_leading_zeroes ... ok test solution_test::test_sub_1_basic ... ok test solution_test::test_sub_2_diferent_lengths ... ok test solution_test::test_sub_3_carry ... ok test solution_test::test_sum_1_basic ... ok test solution_test::test_sum_2_different_lengths ... ok test solution_test::test_sum_3_overflow ... ok test solution_test::test_sum_4_negative ... ok test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out