Решение на Bigint от Деян Горанов
Резултати
- 0 точки от тестове
- 0 бонус точки
- 0 точки общо
- 0 успешни тест(а)
- 0 неуспешни тест(а)
Код
#[derive(Debug, PartialEq, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
const ZERO_SIGN: i8 = 0;
const POSITIVE_SIGN: i8 = 1;
const NEGATIVE_SIGN: i8 = -1;
/// Конструира нов Bigint със стойност "0" и положителен знак.
/// Това може да означава празен вектор с цифри или масив с една цифра `0` -- ваш избор.
///
pub fn new() -> Self {
Bigint { sign: Self::ZERO_SIGN, digits: Vec::new() }
}
/// Конструира нов Bigint с подадените цифри и знак.
///
/// Тук е добро място където можете да вкарате малко валидация и нормализиране на входа -- да
/// премахнете допълнителни нули или да се погрижите, че нулата винаги има консистентен знак.
/// Стига да се погрижите винаги да използвате функцията при конструириане на нови Bigint-ове.
///
/// Тази функция НЕ Е публична, така че НЕ Е задължителна -- ако не ви трябва, може смело да я
/// изтриете.
///
fn from_components(input_sign: i8, input_digits: Vec<u8>) -> Self {
let digits =
input_digits.into_iter()
.skip_while(|&d| d == 0)
.collect::<Vec<u8>>();
let sign =
if digits.is_empty() {
Self::ZERO_SIGN
} else {
input_sign
};
Bigint { sign, digits }
}
/// Връща `true` ако числото е положително. Нулата не е положителна.
pub fn is_positive(&self) -> bool {
self.sign == Self::POSITIVE_SIGN
}
/// Връща `true` ако числото е отрицателно. Нулата не е отрицателна.
pub fn is_negative(&self) -> bool {
self.sign == Self::NEGATIVE_SIGN
}
}
use std::str::FromStr;
#[derive(Debug)]
pub struct ParseError;
impl FromStr for Bigint {
type Err = ParseError;
/// Очакваме низа да е във формат десетично цяло число с опционален знак, тоест всички тези
/// неща би трябвало да върнат `Ok` резултат с конструиран Bigint:
///
/// Това включва нулата, като имате предвид че, както казахме, +0 и -0 трябва да са
/// еквивалентни.
///
/// Ако подадения низ е празен, това връща същото като да сме подали "0". Ако подадения низ е
/// само "+" или "-", ваше решение е дали да е нула или да е грешка, няма да го тестваме.
///
/// Ако подадения низ започва с нули, това няма значение -- игнорират се. Тоест, конструиране с
/// "00123" ще е същото като конструиране с "123".
///
/// Ако сме подали низ, който включва каквито и да е други символи освен цифрите 0-9 (и
/// опционален начален знак), очакваме да върнете `ParseError`.
///
fn from_str(s: &str) -> Result<Self, Self::Err> {
let sign =
if s.chars().nth(0) == Some('-') {
Self::NEGATIVE_SIGN
} else {
Self::POSITIVE_SIGN
};
s.strip_prefix(|c| c == '+' || c == '-')
.unwrap_or(s)
.chars()
.map(|c| c.to_digit(10).map(|x| x as u8))
.collect::<Option<Vec<u8>>>()
.map(|digits| Bigint::from_components(sign, digits))
.ok_or(ParseError)
}
}
use std::cmp::Ordering;
impl PartialOrd for Bigint {
/// Две цели числа винаги могат да се сравнят, така че "частичното" равенство е същото като
/// пълното.
///
fn partial_cmp(&self, other: &Bigint) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Bigint {
/// Ако едното от числата е положително, а другото -- отрицателно, положителното е по-голямо.
///
/// Ако едното от числата има по-голям брой цифри, то ще бъде по-голямото. (Стига да не са нули
/// -- вероятно е добра идея да се погрижите да няма започващи нули при конструкция.)
///
/// Ако двете числа имат еднакъв брой цифри, лексикографско сравнение на числата ще ви даде
/// правилен резултат -- от по-значимите цифри към по-малко значимите. Внимавайте в какъв ред
/// си държите цифритe и дали не трябва да ги обърнете.
///
/// Ако двете числа са отрицателни, сравнението по абсолютна стойност ще е обърнато (-1 е
/// по-голямо от -2) -- погледнете документацията на `Ordering` за това как лесно можете да
/// обърнете резултата.
///
fn cmp(&self, other: &Bigint) -> Ordering {
if self.sign == other.sign {
let l1 = self.digits.len() as u8;
let l2 = other.digits.len() as u8;
let n = std::cmp::max(l1, l2);
let d1 = (0 .. n - l1).collect::<Vec<u8>>();
let d2 = (0 .. n - l2).collect::<Vec<u8>>();
d1.iter().chain(self.digits.iter())
.cmp(d2.iter().chain(other.digits.iter()))
} else {
self.sign.cmp(&other.sign)
}
}
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20201127-2274206-qabsqi/solution)
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:76:30
|
76 | assert_eq!(bigint("1") + bigint("2"), bigint("3"));
| ----------- ^ ----------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:77:30
|
77 | assert_eq!(bigint("111") + bigint("222"), bigint("333"));
| ------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:80:40
|
80 | bigint("11111111111111111111") +
| ------------------------------ ^
| |
| solution::Bigint
81 | bigint("22222222222222222222"),
| ------------------------------ solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:88:31
|
88 | assert_eq!(bigint("12") + bigint("12000"), bigint("12012"));
| ------------ ^ --------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:89:31
|
89 | assert_eq!(bigint("1") + bigint("123"), bigint("124"));
| ----------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:90:31
|
90 | assert_eq!(bigint("111") + bigint("0"), bigint("111"));
| ------------- ^ ----------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:91:31
|
91 | assert_eq!(bigint("0") + bigint("444"), bigint("444"));
| ----------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:92:31
|
92 | assert_eq!(bigint("+123") + bigint("+456"), bigint("579"));
| -------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:97:30
|
97 | assert_eq!(bigint("999") + bigint("1"), bigint("1000"));
| ------------- ^ ----------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:98:30
|
98 | assert_eq!(bigint("511") + bigint("599"), bigint("1110"));
| ------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:100:31
|
100 | assert_eq!(bigint("-999") + bigint("-1"), bigint("-1000"));
| -------------- ^ ------------ solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:101:31
|
101 | assert_eq!(bigint("-511") + bigint("-599"), bigint("-1110"));
| -------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:104:40
|
104 | bigint("99999999999999999999") +
| ------------------------------ ^
| |
| solution::Bigint
105 | bigint("1"),
| ----------- solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:112:31
|
112 | assert_eq!(bigint("-123") + bigint("-456"), bigint("-579"));
| -------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:113:31
|
113 | assert_eq!(bigint("-12") + bigint("-12000"), bigint("-12012"));
| ------------- ^ ---------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:114:31
|
114 | assert_eq!(bigint("-1") + bigint("-123"), bigint("-124"));
| ------------ ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:115:31
|
115 | assert_eq!(bigint("-111") + bigint("-0"), bigint("-111"));
| -------------- ^ ------------ solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:116:31
|
116 | assert_eq!(bigint("-0") + bigint("-444"), bigint("-444"));
| ------------ ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:118:31
|
118 | assert_eq!(bigint("-123") + bigint("456"), bigint("333"));
| -------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:119:31
|
119 | assert_eq!(bigint("123") + bigint("-456"), bigint("-333"));
| ------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:120:31
|
120 | assert_eq!(bigint("456") + bigint("-123"), bigint("333"));
| ------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:121:31
|
121 | assert_eq!(bigint("-456") + bigint("123"), bigint("-333"));
| -------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:126:31
|
126 | assert_eq!(bigint("-123") + bigint("123"), bigint("0"));
| -------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:127:30
|
127 | assert_eq!(bigint("123") + bigint("-123"), bigint("0"));
| ------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:128:29
|
128 | assert_eq!(bigint("-0") + bigint("+0"), bigint("0"));
| ------------ ^ ------------ solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot add `solution::Bigint` to `solution::Bigint`
--> tests/solution_test.rs:129:29
|
129 | assert_eq!(bigint("+0") + bigint("-0"), bigint("0"));
| ------------ ^ ------------ solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:131:31
|
131 | assert_eq!(bigint("123") - bigint("123"), bigint("0"));
| ------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:132:31
|
132 | assert_eq!(bigint("-123") - bigint("-123"), bigint("0"));
| -------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:133:31
|
133 | assert_eq!(bigint("-0") - bigint("-0"), bigint("0"));
| ------------ ^ ------------ solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:134:31
|
134 | assert_eq!(bigint("+0") - bigint("+0"), bigint("0"));
| ------------ ^ ------------ solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:139:30
|
139 | assert_eq!(bigint("567") - bigint("123"), bigint("444"));
| ------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:140:30
|
140 | assert_eq!(bigint("123") - bigint("567"), bigint("-444"));
| ------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:143:40
|
143 | bigint("33333333333333333333") -
| ------------------------------ ^
| |
| solution::Bigint
144 | bigint("22222222222222222222"),
| ------------------------------ solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:151:31
|
151 | assert_eq!(bigint("1100") - bigint("100"), bigint("1000"));
| -------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:152:31
|
152 | assert_eq!(bigint("1567") - bigint("123"), bigint("1444"));
| -------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:157:31
|
157 | assert_eq!(bigint("1000") - bigint("1"), bigint("999"));
| -------------- ^ ----------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:158:31
|
158 | assert_eq!(bigint("1110") - bigint("599"), bigint("511"));
| -------------- ^ ------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:159:31
|
159 | assert_eq!(bigint("123") - bigint("1567"), bigint("-1444"));
| ------------- ^ -------------- solution::Bigint
| |
| solution::Bigint
error[E0369]: cannot subtract `solution::Bigint` from `solution::Bigint`
--> tests/solution_test.rs:162:41
|
162 | bigint("100000000000000000000") -
| ------------------------------- ^
| |
| solution::Bigint
163 | bigint("1"),
| ----------- solution::Bigint
error: aborting due to 39 previous errors
For more information about this error, try `rustc --explain E0369`.
error: could not compile `solution`
To learn more, run the command again with --verbose.
История (2 версии и 3 коментара)
Деян качи решение на 27.11.2020 16:55 (преди почти 5 години)
#[derive(Debug, PartialEq, Eq)]
pub struct Bigint {
sign: i8,
digits: Vec<u8>,
}
impl Bigint {
const ZERO_SIGN: i8 = 0;
const POSITIVE_SIGN: i8 = 1;
const NEGATIVE_SIGN: i8 = -1;
/// Конструира нов Bigint със стойност "0" и положителен знак.
/// Това може да означава празен вектор с цифри или масив с една цифра `0` -- ваш избор.
///
pub fn new() -> Self {
Bigint { sign: Self::ZERO_SIGN, digits: Vec::new() }
}
/// Конструира нов Bigint с подадените цифри и знак.
///
/// Тук е добро място където можете да вкарате малко валидация и нормализиране на входа -- да
/// премахнете допълнителни нули или да се погрижите, че нулата винаги има консистентен знак.
/// Стига да се погрижите винаги да използвате функцията при конструириане на нови Bigint-ове.
///
/// Тази функция НЕ Е публична, така че НЕ Е задължителна -- ако не ви трябва, може смело да я
/// изтриете.
///
fn from_components(input_sign: i8, input_digits: Vec<u8>) -> Self {
let digits =
input_digits.into_iter()
.skip_while(|&d| d == 0)
.collect::<Vec<u8>>();
let sign =
if digits.is_empty() {
Self::ZERO_SIGN
} else {
input_sign
};
Bigint { sign, digits }
}
/// Връща `true` ако числото е положително. Нулата не е положителна.
pub fn is_positive(&self) -> bool {
self.sign == Self::POSITIVE_SIGN
}
/// Връща `true` ако числото е отрицателно. Нулата не е отрицателна.
pub fn is_negative(&self) -> bool {
self.sign == Self::NEGATIVE_SIGN
}
}
use std::str::FromStr;
#[derive(Debug)]
pub struct ParseError;
impl FromStr for Bigint {
type Err = ParseError;
/// Очакваме низа да е във формат десетично цяло число с опционален знак, тоест всички тези
/// неща би трябвало да върнат `Ok` резултат с конструиран Bigint:
///
- /// Bigint::from_str("123") // => положителен знак по подразбиране
- /// Bigint::from_str("+123")
- /// Bigint::from_str("-123")
- ///
/// Това включва нулата, като имате предвид че, както казахме, +0 и -0 трябва да са
/// еквивалентни.
///
/// Ако подадения низ е празен, това връща същото като да сме подали "0". Ако подадения низ е
/// само "+" или "-", ваше решение е дали да е нула или да е грешка, няма да го тестваме.
///
/// Ако подадения низ започва с нули, това няма значение -- игнорират се. Тоест, конструиране с
/// "00123" ще е същото като конструиране с "123".
///
/// Ако сме подали низ, който включва каквито и да е други символи освен цифрите 0-9 (и
/// опционален начален знак), очакваме да върнете `ParseError`.
///
fn from_str(s: &str) -> Result<Self, Self::Err> {
let sign =
if s.chars().nth(0) == Some('-') {
Self::NEGATIVE_SIGN
} else {
Self::POSITIVE_SIGN
};
s.strip_prefix(|c| c == '+' || c == '-')
.unwrap_or(s)
.chars()
.map(|c| c.to_digit(10).map(|x| x as u8))
.collect::<Option<Vec<u8>>>()
.map(|digits| Bigint::from_components(sign, digits))
.ok_or(ParseError)
}
}
use std::cmp::Ordering;
impl PartialOrd for Bigint {
/// Две цели числа винаги могат да се сравнят, така че "частичното" равенство е същото като
/// пълното.
///
fn partial_cmp(&self, other: &Bigint) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Bigint {
/// Ако едното от числата е положително, а другото -- отрицателно, положителното е по-голямо.
///
/// Ако едното от числата има по-голям брой цифри, то ще бъде по-голямото. (Стига да не са нули
/// -- вероятно е добра идея да се погрижите да няма започващи нули при конструкция.)
///
/// Ако двете числа имат еднакъв брой цифри, лексикографско сравнение на числата ще ви даде
/// правилен резултат -- от по-значимите цифри към по-малко значимите. Внимавайте в какъв ред
/// си държите цифритe и дали не трябва да ги обърнете.
///
/// Ако двете числа са отрицателни, сравнението по абсолютна стойност ще е обърнато (-1 е
/// по-голямо от -2) -- погледнете документацията на `Ordering` за това как лесно можете да
/// обърнете резултата.
///
fn cmp(&self, other: &Bigint) -> Ordering {
if self.sign == other.sign {
let l1 = self.digits.len() as u8;
let l2 = other.digits.len() as u8;
let n = std::cmp::max(l1, l2);
let d1 = (0 .. n - l1).collect::<Vec<u8>>();
let d2 = (0 .. n - l2).collect::<Vec<u8>>();
d1.iter().chain(self.digits.iter())
.cmp(d2.iter().chain(other.digits.iter()))
} else {
self.sign.cmp(&other.sign)
}
}
}
Кода ти не се компилира, защото нямаш имплементации на Add и Sub, така че няма как да получиш точки. Казахме го в общия guide: https://fmi.rust-lang.bg/tasks/guide. Конкретно:
Изпълнете примерния тест. Ако кода ви не се компилира на примерния тест, ще получите 0 точки. Проверете, че типовете на функциите и структурите ви са същите, които сме описали в условието. Ако решите да върнете тип Foo вместо описания тип &Foo, нашите тестове просто няма да се компилират и ще получите 0 точки.
Ако беше предал по-рано, щях да те предупредя поне.
Ох, забравих. Толкова за в последния момент :(
Мда. Кофти е, но ще гледаме да даваме още предизвикателства за бонус точки с шансове за наваксване.
