Решение на 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 точки.
Ако беше предал по-рано, щях да те предупредя поне.
Ох, забравих. Толкова за в последния момент :(
Мда. Кофти е, но ще гледаме да даваме още предизвикателства за бонус точки с шансове за наваксване.