Решение на Дигитален корен от Александра Йовкова

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

Към профила на Александра Йовкова

Резултати

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

Код

fn get_sum(n: u32) -> u32 {
let mut sum = 0_u32;
let mut temp = n;
while temp > 0 {
sum += temp % 10;
temp = temp / 10;
}
sum
}
pub fn decimal(input: &str) -> Option<u32> {
let mut num = match u32::from_str_radix(input, 10) {
Ok(num) => num,
Err(_) => return None,
};
let mut x: Option<u32> = None;
while num > 9 {
num = get_sum(num);
}
x = Some(num);
x
}

Не ти трябва временната стойност x. Даже Rust би трябвало да ти даде warning, че началната стойност на x никога не се чете. Кода може да е такъв:

while num > 9 {
    num = get_sum(num);
}
Some(num)
pub fn binary(input: &str) -> Option<u32> {
let num = match u32::from_str_radix(input, 2) {
Ok(num) => num,
Err(_) => return None,
};
let mut result: Option<u32> = None;
if num != 0 {
result = Some(1);
} else {
result = Some(0);
}
result

Пак имаш временна променлива, която не е нужна. Функцията може да завършва на:

if num != 0 {
    Some(1)
} else {
    Some(0)
}

Тъй като if-клаузата е израз, спокойно последния израз на функцията бива върнат, а той ще е един от ръкавите на if-а.

}
pub fn hex(input: &str) -> Option<u32> {
let mut sum = 0_u32;
for c in input.chars() {
let hex_digit = c.to_digit(16); // returns Option with None if digit is invalid
if hex_digit == None {
return None;
}
sum += hex_digit.unwrap();
}

Вместо ръчно да сравняваш с None (има метод .is_none() впрочем), можеш директно да pattern-match-неш:

for c in input.chars() {
    if let Some(hex_digit) = c.to_digit(16) { // returns Option with None if digit is invalid
        sum += hex_digit;
    } else {
        return None;
    }
}

Като допълнителен бонус, променливата hex_digit наистина е цифра, а не Option<цифра> което е малко по-интуитивно свързано с името.

if sum > 15 {
let new_input_hex = format!("{:x}", sum);
return hex(&new_input_hex);
}
let root = match sum {
1 => 0x_1_u32,
2 => 0x_2_u32,
3 => 0x_3_u32,
4 => 0x_4_u32,
5 => 0x_5_u32,
6 => 0x_6_u32,
7 => 0x_7_u32,
8 => 0x_8_u32,
9 => 0x_9_u32,
10 => 0x_a_u32,
11 => 0x_b_u32,
12 => 0x_c_u32,
13 => 0x_d_u32,
14 => 0x_e_u32,
15 => 0x_f_u32,
_ => 0x_0_u32,
};

Обстойно :). Но не ти трябва -- 1 и 0x_1_u32 са едно и също нещо, също както 15 и 0x_0_u32. Синтаксиса с 0x не създава стойност от различен тип, а пак си прави стойност от тип u32, просто литерала е различен. 0xf ти е числото 15.

Ефективно, тук правиш let root = sum, освен че ако е 0 или над 15 става 0, но това са случаи, до които не би трябвало да може да се стигне.

Some(root)
}
pub fn octal(input: &str) -> Option<u32> {
let mut sum = 0_u32;
for c in input.chars() {
let oct_digit = c.to_digit(8); // returns Option with None if digit is invalid
if oct_digit == None {
return None;
}
sum += oct_digit.unwrap();
}
if sum > 7 {
let new_input_oct = format!("{:o}", sum);
return octal(&new_input_oct);
}
Some(sum)
}

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

Compiling solution v0.1.0 (/tmp/d20200111-2173579-mcti97/solution)
warning: value assigned to `x` is never read
  --> src/lib.rs:16:13
   |
16 |     let mut x: Option<u32> = None;
   |             ^
   |
   = note: `#[warn(unused_assignments)]` on by default
   = help: maybe it is overwritten before being read?

warning: value assigned to `result` is never read
  --> src/lib.rs:30:13
   |
30 |     let mut result: Option<u32> = None;
   |             ^^^^^^
   |
   = help: maybe it is overwritten before being read?

warning: value assigned to `x` is never read
  --> src/lib.rs:16:13
   |
16 |     let mut x: Option<u32> = None;
   |             ^
   |
   = note: `#[warn(unused_assignments)]` on by default
   = help: maybe it is overwritten before being read?

warning: value assigned to `result` is never read
  --> src/lib.rs:30:13
   |
30 |     let mut result: Option<u32> = None;
   |             ^^^^^^
   |
   = help: maybe it is overwritten before being read?

    Finished test [unoptimized + debuginfo] target(s) in 3.47s
     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 версия и 5 коментара)

Александра качи първо решение на 03.11.2019 16:57 (преди почти 6 години)

Решението ти е прилежно, направено стъпка по стъпка, но си заслужава след като го напишеш да го прочетеш 1-2 пъти и да се опиташ да го опростиш -- кои временни променливи не ти трябват и/или кода ще бъде по-прост без тях? Какви типове имат променливите и удобни ли са тези типове (така можеше евентуално да стигнеш до въпроса какъв тип е sum и какъв е root и да осъзнаеш, че са едни и същи)?