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

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

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

Резултати

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

Код

fn is_correct(input: &str, base: u32) -> bool {
if input.is_empty(){
return false
}
let input_characters = input.chars();
for ch in input_characters{
if !ch.is_digit(base) {
return false
}
}
true
}
fn calculate_digital_root(input: &str, base: u32) -> Option<u32>{
let input = input.trim();
if !is_correct(input,base){
return None
} else if input == "0"{
return Some(0);
}
let mut result = 0;
for c in input.chars() {
result = (result + c.to_digit(base).unwrap()) % (base-1);
}

Тук използваш .unwrap(), което е ок като логика, понеже по-горе си валидирал входа. Предимството на този подход е че валидацията може да бъде доста сложна и съответно можеш да я енкапсулираш в нещо отделно. Недостатъци, които аз виждам, са че 1) loop-ваш два пъти по символите в позитивния случай и 2) ако допуснеш грешка във валидацията, кода ще се счупи тук, което ще е по-трудно за дебъгване.

В този код, нито едно от двете не е голям проблем. В по-сложна ситуация, може да ти попречи тази структура -- зависи и донякъде е въпрос и на вкус. Но rust ти дава добри инструменти за едновременно валидиране и вземане на стойност -- ако просто заместиш този .unwrap() с ?, мисля че директно можеш да махнеш is_valid функцията (не съм 100% сигурен, но така ми изглежда). Просто нещо, за което да помислиш за по-нататък.

match result{
0 => Some(base-1),
_ => Some(result % (base-1)),
}
}
fn count_ones(input: &str) -> u32{
let mut count = 0;
for c in input.chars() {
if c == '1' {
count = count + 1;
}
}
count
}
// Десетична бройна система: 0-9
pub fn decimal(input: &str) -> Option<u32> {
calculate_digital_root(input,10)
}
/// Шестнадесетична бройна система: 0-9, последвано от a-f
pub fn hex(input: &str) -> Option<u32> {
calculate_digital_root(input,16)
}
///Осмична бройна система: 0-7
pub fn octal(input: &str) -> Option<u32> {
calculate_digital_root(input,8)
}
/// Двоична бройна система: 0-1
pub fn binary(input: &str) -> Option<u32> {
let input = input.trim();
if !is_correct(input,2){
return None
}
match count_ones(input){
0 => Some(0),
_ => Some(1),
}

На теория, може би просто можеш да провериш дали низа е "0"? Either way, добре си се сетил, че за двоични числа може да е само 1, ако имаш поне една единица :).

}

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

Compiling solution v0.1.0 (/tmp/d20200111-2173579-jmaf9j/solution)
    Finished test [unoptimized + debuginfo] target(s) in 1.76s
     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

История (2 версии и 3 коментара)

Стефан качи първо решение на 31.10.2019 21:58 (преди почти 6 години)

Стефан качи решение на 03.11.2019 16:17 (преди почти 6 години)

fn is_correct(input: &str, base: u32) -> bool {
+ if input.is_empty(){
+ return false
+ }
let input_characters = input.chars();
-
for ch in input_characters{
if !ch.is_digit(base) {
return false
}
}
true
}
-fn calculate(input: &str, base: u32) -> Option<u32>{
+fn calculate_digital_root(input: &str, base: u32) -> Option<u32>{
let input = input.trim();
if !is_correct(input,base){
return None
} else if input == "0"{
return Some(0);
}
let mut result = 0;
for c in input.chars() {
result = (result + c.to_digit(base).unwrap()) % (base-1);
}

Тук използваш .unwrap(), което е ок като логика, понеже по-горе си валидирал входа. Предимството на този подход е че валидацията може да бъде доста сложна и съответно можеш да я енкапсулираш в нещо отделно. Недостатъци, които аз виждам, са че 1) loop-ваш два пъти по символите в позитивния случай и 2) ако допуснеш грешка във валидацията, кода ще се счупи тук, което ще е по-трудно за дебъгване.

В този код, нито едно от двете не е голям проблем. В по-сложна ситуация, може да ти попречи тази структура -- зависи и донякъде е въпрос и на вкус. Но rust ти дава добри инструменти за едновременно валидиране и вземане на стойност -- ако просто заместиш този .unwrap() с ?, мисля че директно можеш да махнеш is_valid функцията (не съм 100% сигурен, но така ми изглежда). Просто нещо, за което да помислиш за по-нататък.

match result{
0 => Some(base-1),
_ => Some(result % (base-1)),
}
}
fn count_ones(input: &str) -> u32{
let mut count = 0;
for c in input.chars() {
if c == '1' {
count = count + 1;
}
}
count
}
// Десетична бройна система: 0-9
pub fn decimal(input: &str) -> Option<u32> {
- calculate(input,10)
+ calculate_digital_root(input,10)
}
/// Шестнадесетична бройна система: 0-9, последвано от a-f
pub fn hex(input: &str) -> Option<u32> {
- calculate(input,16)
+ calculate_digital_root(input,16)
}
///Осмична бройна система: 0-7
pub fn octal(input: &str) -> Option<u32> {
- calculate(input,8)
+ calculate_digital_root(input,8)
}
/// Двоична бройна система: 0-1
pub fn binary(input: &str) -> Option<u32> {
let input = input.trim();
if !is_correct(input,2){
return None
}
match count_ones(input){
0 => Some(0),
_ => Some(1),
}

На теория, може би просто можеш да провериш дали низа е "0"? Either way, добре си се сетил, че за двоични числа може да е само 1, ако имаш поне една единица :).

}

Добро решение. На някои места имаш малко странна индентация -- не е голям проблем, но си заслужава човек да си подрежда кода, помага със самодисциплината :).