Решение на Дигитален корен от Николай Захаров

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

Към профила на Николай Захаров

Резултати

  • 20 точки от тестове
  • 1 бонус точка
  • 21 точки общо
  • 6 успешни тест(а)
  • 0 неуспешни тест(а)

Код

/// Десетична бройна система: 0-9
pub fn decimal(input: &str) -> Option<u32> {
calc_digital_root(input, Base::Decimal)
}
/// Шестнадесетична бройна система: 0-9, последвано от a-f
pub fn hex(input: &str) -> Option<u32> {
calc_digital_root(input, Base::Hex)
}
/// Осмична бройна система: 0-7
pub fn octal(input: &str) -> Option<u32> {
calc_digital_root(input, Base::Octal)
}
/// Двоична бройна система: 0-1
pub fn binary(input: &str) -> Option<u32> {
calc_digital_root(input, Base::Binary)
}
#[derive(Copy, Clone)]
enum Base {
Decimal = 10,
Hex = 16,
Octal = 8,
Binary = 2,
}

Хитро решение с enum -- не се бях сетил, че можеш после да го конвертираш до число чрез as оператора. Това има доста смисъл в контекста на задачата и лесно interface-ва с вградените функции, които приемат число за бройна система.

fn calc_digital_root(input: &str, base: Base) -> Option<u32> {
if input.len() == 0 {
return None;
}
let mut sum: u32;
let mut str_sum = String::from(input);
while str_sum.len() > 1 {
let digits: Option<Vec<u32>> = str_sum
.chars()
.map(|c| c.to_digit(base as u32))
.collect();
if digits.is_none() {
return None;
}
sum = digits
.unwrap()
.iter()
.sum();

Тези два блока код могат да се възползват от това, че функцията връща Option и оператора ? работи за Option:

let digits: Option<Vec<u32>> = str_sum
    .chars()
    .map(|c| c.to_digit(base as u32))
    .collect();

sum = digits?.iter().sum();

По-компактно е, макар че може да се направи аргумент че е по-малко ясно. Still, избягва употреба на unwrap.

Променливата sum няма нужда да бъде дефинирана извън цикъла. Единственото състояние, което поддържаш е str_sum, числовата променлива може да си бъде декларирана вътре в loop-а.

str_sum = match base {
Base::Decimal => format!("{}", sum),
Base::Binary => format!("{:b}", sum),
Base::Octal => format!("{:o}", sum),
Base::Hex => format!("{:x}", sum)
};
}
str_sum
.chars()
.next()
.unwrap()
.to_digit(base as u32)
}

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

Compiling solution v0.1.0 (/tmp/d20200111-2173579-2rhikr/solution)
    Finished test [unoptimized + debuginfo] target(s) in 2.96s
     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 ... ok
test solution_test::test_invalid ... ok
test solution_test::test_octal_basic ... ok
test solution_test::test_zeroes ... ok

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

   Doc-tests solution

running 0 tests

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

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

Николай качи първо решение на 04.11.2019 19:58 (преди почти 6 години)

Добра работа. Давам ти бонус точка за креативната употреба на enums и на .collect() за да превърнеш Result<Option<u32>> във Option<Result<u32>>. Ако не си го направил нарочно, проследи типовете внимателно при употребата на collect и ще видиш че точно това се е случило :).