Решение на 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
