Решение на Дигитален корен от Иво Стефанов

Обратно към всички решения

Към профила на Иво Стефанов

Резултати

  • 7 точки от тестове
  • 0 бонус точки
  • 7 точки общо
  • 2 успешни тест(а)
  • 4 неуспешни тест(а)

Код

use std::str;
use std::char;
pub fn decimal(input: &str) -> Option<u32> {
let num = input.parse::<u32>();
let mut string = input.to_string().clone();
if num.is_ok(){
let mut sum = string.chars().map(|c| c.to_digit(10).unwrap()).sum::<u32>();
while sum > 9{
string = sum.to_string();
sum = string.chars().map(|c| c.to_digit(10).unwrap()).sum::<u32>();
}
Some(sum)
}
else{
None
}
}
pub fn hex(input: &str) -> Option<u32> {
for c in input.chars(){
if "0123456789abcdef".chars().any(|h| h == c) == false{
return None;
}
}
let mut string = input.to_string().clone();
let mut sum = 1;
while string.chars().count() > 1{
sum = string.chars().map(|c| c.to_digit(16).unwrap()).sum::<u32>();
string = to_hex(sum);
}
Some(sum)
}
pub fn octal(input: &str) -> Option<u32> {
for c in input.chars(){
if "012345678".chars().any(|o| o == c) == false{
return None;
}
}
let mut string = input.to_string().clone();
let mut sum = 1;
while string.chars().count() > 1{
sum = string.chars().map(|c| c.to_digit(8).unwrap()).sum::<u32>();
string = to_oct(sum);
}
Some(sum)
}
pub fn binary(input: &str) -> Option<u32> {
for c in input.chars(){
if "01".chars().any(|b| b == c) == false{
return None;
}
}
for c in input.chars(){
if c == '1'{
return Some(1);
}
}
Some(0)
}
fn to_oct (mut dec: u32) -> String{
let mut oct = String::from("");
while dec > 0{
match dec%8{
c @ 0..=7 => oct.push(char::from_digit(c,8).unwrap()),
_ => (),
}

Този match statement е малко странен. Няма как числото dec%8 да бъде по-голямо от 7. Дори и да кажем, че искаш да се предпазиш от програмистка грешка, в другия ръкав на match-а не правиш нищо така или иначе, така че няма много смисъл да имаш match тук. Можеше да викнеш unreachable!() примерно, и щях да приема, че може би пишеш по-дефанзивно. (Пак не мисля, че щеше да има смисъл в случая.)

Този код можеше просто да бъде oct.push(char::from_digit(dec % 8, 8).unwrap(), последвано от долното dec /= 8, basically. Същото за долния. Иначе, можеше и да заместиш цялата функция с format!("{:o}", dec), но е ок да не си разучил различните format specifiers (но направи го сега :)).

dec/=8;
}
oct.chars().rev().collect()
}
fn to_hex (mut dec: u32) -> String{
let mut hex = String::from("");
while dec > 0{
match dec%16{
c @ 0..=15 => hex.push(char::from_digit(c,16).unwrap()),
_ => (),
}
dec/=16;
}
hex.chars().rev().collect()
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20200111-2173579-e23w0p/solution)
    Finished test [unoptimized + debuginfo] target(s) in 2.97s
     Running target/debug/deps/solution-a73e64ec87929bd0

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-38971695424b36d5

running 6 tests
test solution_test::test_binary ... ok
test solution_test::test_decimal_basic ... ok
test solution_test::test_hex_basic ... FAILED
test solution_test::test_invalid ... FAILED
test solution_test::test_octal_basic ... FAILED
test solution_test::test_zeroes ... FAILED

failures:

---- solution_test::test_hex_basic stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Some(1)`,
 right: `Some(0)`', tests/solution_test.rs:23:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

---- solution_test::test_invalid stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Some(1)`,
 right: `None`', tests/solution_test.rs:64:5

---- solution_test::test_octal_basic stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Some(1)`,
 right: `Some(0)`', tests/solution_test.rs:37:9

---- solution_test::test_zeroes stdout ----
thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `Some(1)`,
 right: `Some(0)`', tests/solution_test.rs:55:5


failures:
    solution_test::test_hex_basic
    solution_test::test_invalid
    solution_test::test_octal_basic
    solution_test::test_zeroes

test result: FAILED. 2 passed; 4 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'

История (1 версия и 4 коментара)

Иво качи първо решение на 05.11.2019 11:48 (преди почти 6 години)

На няколко места имаш употреба на неща като .to_digit(...).unwrap(). Причината за това е, че първо правиш валидация и после разчиташ, че числото е валидно. Вместо това, можеш да използваш факта, че .to_digit() връща Option, за да валидираш докато циклиш по символите. Това би избегнало и доста ръчна валидация по символи, и грешки идващи от нея -- примерно, на едно място кода смята, че 8 е валидно число.

Като цяло те съветвам и да си тестваш кода внимателно. Имаш логически грешки, които можеха да бъдат избегнати, ако беше пробвал с повече примери, със 0 особено. Виж пълния тест, който сме качили и мисли за следващия път как ще си тестваш сам кода.