Решение на Bigint от Кристиян Стоянов
Към профила на Кристиян Стоянов
Резултати
- 6 точки от тестове
- 0 бонус точки
- 6 точки общо
- 6 успешни тест(а)
- 9 неуспешни тест(а)
Код
use std::str::FromStr;
use std::cmp::Ordering;
#[derive(Debug, PartialEq, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
pub fn new() -> Self {
let mut temp=Vec::<u8>::new();
temp.push(0);
Bigint {
sign: 1,
digits:temp,
}
}
pub fn is_positive(&self) -> bool
{
return self.sign != 0
}
pub fn is_negative(&self) -> bool
{
return self.sign == 0
}
}
#[derive(Debug)]
pub struct ParseError;
impl FromStr for Bigint
{
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err>
{
if s.is_empty()
{
let mut temp=Vec::<u8>::new();
temp.push(0);
let t = 0 as i8;
return Ok(Bigint{ sign: t,digits: temp });
}
let mut chars: Vec<char> = s.chars().collect();
let mut is_positive=false;
if chars[0]=='-'
{
chars=(&chars[1..]).to_vec();
}else if chars[0]=='+'
{
chars=(&chars[1..]).to_vec();
is_positive=true;
}
else if chars[0]>='0' && chars[0]<='9'
{
is_positive=true;
}
else
{
return Err(ParseError);
}
let mut is_positives;
if is_positive
{
is_positives=1 as i8;
}
else{
is_positives=0 as i8;
}
if chars.is_empty()
{
return Err(ParseError);
}
let mut tempnumber=0;
while tempnumber<chars.iter().count()
{
if chars[tempnumber]<'0' || chars[tempnumber]>'9'
{
return Err(ParseError);
}
tempnumber=tempnumber+1;
}
while chars[0]=='0'
{
if chars.iter().count()!=1
{
chars=(&chars[1..]).to_vec();
}
else
{
is_positives=1;
break;
}
}
let mut number=0;
let mut tempdigits: Vec<u8>=Vec::new();
while number<chars.iter().count()
{
let x=chars[number];
tempdigits.push(x as u8 -48);
number=number+1;
}
return Ok(Bigint{ sign: is_positives,digits: tempdigits });
}
}
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.is_positive() && other.is_negative()
{
return Ordering::Greater;
}
else if self.is_negative() && other.is_positive()
{
return Ordering::Less;
}
else if self.is_positive() && other.is_positive()
{
if self.digits.iter().count()>other.digits.iter().count()
{
return Ordering::Greater;
}
else if self.digits.iter().count()<other.digits.iter().count()
{
return Ordering::Less;
}
else//equal number of digits
{
let mut tempdigitcounter=0;
while tempdigitcounter<self.digits.iter().count()
{
if self.digits[tempdigitcounter]>other.digits[tempdigitcounter]
{
return Ordering::Greater;
}else if self.digits[tempdigitcounter]<other.digits[tempdigitcounter]
{
return Ordering::Less;
}
tempdigitcounter=tempdigitcounter+1;
}
return Ordering::Equal;
}
}
else //both are negative
{
if self.digits.iter().count()>other.digits.iter().count()
{
return Ordering::Less;
}
else if self.digits.iter().count()<other.digits.iter().count()
{
return Ordering::Greater;
}
else//equal number of digits
{
let mut tempdigitcounter=0;
while tempdigitcounter<self.digits.iter().count()
{
if self.digits[tempdigitcounter]>other.digits[tempdigitcounter]
{
return Ordering::Less;
}else if self.digits[tempdigitcounter]<other.digits[tempdigitcounter]
{
return Ordering::Greater;
}
tempdigitcounter=tempdigitcounter+1;
}
return Ordering::Equal;
}
}
}
}
use std::ops::{Add, Sub};
impl Add for Bigint {
type Output = Bigint;
fn add(self, other: Self) -> Self {
if self.sign==1 && other.sign==1 || self.sign==0 && other.sign==0
{
let mut p=self.digits;
let mut s=other.digits;
let mut tempdigits: Vec<u8>=Vec::new();
let mut numbers_in_lesser_number;
if p.iter().count()<s.iter().count()
{
numbers_in_lesser_number=p.iter().count();
}
else{
numbers_in_lesser_number=s.iter().count();
}
let mut tempnumber=0;
let mut decimals=0;
while tempnumber<numbers_in_lesser_number
{
let mut t=p[tempnumber]+s[tempnumber];
t=t+decimals;
decimals=0;
if t>=10
{
t=t-10;
decimals=1;
}
tempdigits.push(t);
tempnumber=tempnumber+1;
}
if tempdigits.iter().count()<p.iter().count()
{
tempdigits.push(p[tempnumber] + decimals);
decimals=0;
let mut k=tempdigits.iter().count();
while k<p.iter().count()
{
tempdigits.push(p[k]);
k=k+1;
}
}else if tempdigits.iter().count()<s.iter().count()
{
tempdigits.push(s[tempnumber] + decimals);
decimals=0;
let mut k=tempdigits.iter().count();
while k<s.iter().count()
{
tempdigits.push(s[k]);
k=k+1;
}
} else
{
if decimals==1
{
tempdigits.push(decimals);
}
}
return Bigint{sign: self.sign, digits:tempdigits};
}
else
{
if self.sign==0
{
return other - self;
}
else
{
return self - other;
}
}
}
}
impl Sub for Bigint {
type Output = Bigint;
fn sub(self, other: Self) -> Self {
return self;
}
}
fn bigint(s: &str) -> Bigint {
Bigint::from_str(s).unwrap()
}
fn main()
{
assert_eq!(Bigint::new(), bigint("0"));
assert!(Bigint::from_str("foobar").is_err());
assert!(bigint("1").is_positive());
assert!(bigint("-1").is_negative());
assert!(bigint("123") < bigint("1223"));
println!("{:?}",bigint("123") + bigint("456"));
assert_eq!(bigint("123") + bigint("456"), bigint("579"));
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20201127-2274206-1el6fp6/solution) warning: value assigned to `decimals` is never read --> src/lib.rs:229:17 | 229 | decimals=0; | ^^^^^^^^ | = note: `#[warn(unused_assignments)]` on by default = help: maybe it is overwritten before being read? warning: value assigned to `decimals` is never read --> src/lib.rs:239:17 | 239 | decimals=0; | ^^^^^^^^ | = help: maybe it is overwritten before being read? warning: unused variable: `other` --> src/lib.rs:272:18 | 272 | fn sub(self, other: Self) -> Self { | ^^^^^ help: if this is intentional, prefix it with an underscore: `_other` | = note: `#[warn(unused_variables)]` on by default warning: variable does not need to be mutable --> src/lib.rs:199:13 | 199 | let mut p=self.digits; | ----^ | | | help: remove this `mut` | = note: `#[warn(unused_mut)]` on by default warning: variable does not need to be mutable --> src/lib.rs:200:12 | 200 | let mut s=other.digits; | ----^ | | | help: remove this `mut` warning: variable does not need to be mutable --> src/lib.rs:202:12 | 202 | let mut numbers_in_lesser_number; | ----^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: remove this `mut` warning: function is never used: `bigint` --> src/lib.rs:277:4 | 277 | fn bigint(s: &str) -> Bigint { | ^^^^^^ | = note: `#[warn(dead_code)]` on by default warning: function is never used: `main` --> src/lib.rs:282:4 | 282 | fn main() | ^^^^ warning: 8 warnings emitted Finished test [unoptimized + debuginfo] target(s) in 1.59s Running target/debug/deps/solution_test-589a43f0f4b10ca3 running 15 tests test solution_test::test_bigint_construction ... FAILED test solution_test::test_bigint_nonzero_sign ... ok test solution_test::test_bigint_zero_sign ... FAILED test solution_test::test_comparison ... ok test solution_test::test_invalid_string ... ok test solution_test::test_neutralization ... FAILED 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 ... FAILED test solution_test::test_sub_2_diferent_lengths ... FAILED test solution_test::test_sub_3_carry ... FAILED test solution_test::test_sum_1_basic ... ok test solution_test::test_sum_2_different_lengths ... FAILED test solution_test::test_sum_3_overflow ... FAILED test solution_test::test_sum_4_negative ... FAILED failures: ---- solution_test::test_bigint_construction stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 1, digits: [0] }`, right: `Bigint { sign: 0, digits: [0] }`', tests/solution_test.rs:15:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ---- solution_test::test_bigint_zero_sign stdout ---- thread 'main' panicked at 'assertion failed: !zero.is_positive()', tests/solution_test.rs:21:5 ---- solution_test::test_neutralization stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 1, digits: [1, 2, 3] }`, right: `Bigint { sign: 1, digits: [0] }`', tests/solution_test.rs:126:5 ---- solution_test::test_sub_1_basic stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 1, digits: [5, 6, 7] }`, right: `Bigint { sign: 1, digits: [4, 4, 4] }`', tests/solution_test.rs:139:5 ---- solution_test::test_sub_2_diferent_lengths stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 1, digits: [1, 1, 0, 0] }`, right: `Bigint { sign: 1, digits: [1, 0, 0, 0] }`', tests/solution_test.rs:151:5 ---- solution_test::test_sub_3_carry stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 1, digits: [1, 0, 0, 0] }`, right: `Bigint { sign: 1, digits: [9, 9, 9] }`', tests/solution_test.rs:157:5 ---- solution_test::test_sum_2_different_lengths stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 1, digits: [2, 4, 0, 0, 0] }`, right: `Bigint { sign: 1, digits: [1, 2, 0, 1, 2] }`', tests/solution_test.rs:88:5 ---- solution_test::test_sum_3_overflow stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 1, digits: [0, 10, 9] }`, right: `Bigint { sign: 1, digits: [1, 0, 0, 0] }`', tests/solution_test.rs:97:5 ---- solution_test::test_sum_4_negative stdout ---- thread 'main' panicked at 'assertion failed: `(left == right)` left: `Bigint { sign: 0, digits: [2, 4, 0, 0, 0] }`, right: `Bigint { sign: 0, digits: [1, 2, 0, 1, 2] }`', tests/solution_test.rs:113:5 failures: solution_test::test_bigint_construction solution_test::test_bigint_zero_sign solution_test::test_neutralization solution_test::test_sub_1_basic solution_test::test_sub_2_diferent_lengths solution_test::test_sub_3_carry solution_test::test_sum_2_different_lengths solution_test::test_sum_3_overflow solution_test::test_sum_4_negative test result: FAILED. 6 passed; 9 failed; 0 ignored; 0 measured; 0 filtered out error: test failed, to rerun pass '--test solution_test'