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

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

Към профила на Дойчин Атанасов

Резултати

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

Код

use std::string::String;
/// Десетична бройна система: 0-9
pub fn decimal(input: &str) -> Option<u32> {
find_digital_root(input, 10)
}
/// Шестнадесетична бройна система: 0-9, последвано от a-f
pub fn hex(input: &str) -> Option<u32> {
find_digital_root(input, 16)
}
/// Осмична бройна система: 0-7
pub fn octal(input: &str) -> Option<u32> {
find_digital_root(input, 8)
}
/// Двоична бройна система: 0-1
pub fn binary(input: &str) -> Option<u32> {
find_digital_root(input, 2)
}
fn find_digital_root(input: &str, radix: u32) -> Option<u32> {
if input.len() < 1 {
return None
}
if input.len() == 1 {
return input.chars().next().unwrap().to_digit(radix);
}

Може да заместиш тези две if-клаузи, използвайки оператора ?:

if input.len() <= 1 {
    return input.chars().next()?.to_digit(radix);
}

Дали е добра идея -- зависи. С две отделни if-клаузи стават малко по-ясни различните два случая. Въпросчето по средата на реда може освен това да се изгуби малко, така че ако не друго, може би поне бих направил това:

if input.len() <= 1 {
    let only_char = input.chars().next()?;
    return only_char.to_digit(radix);
}
let mut sum: u32 = 0;
for ch in input.chars() {
match ch.to_digit(radix) {
None => return None,
Some(v) => sum += v,
};
}
let n: String;
if radix == 10 {
n = format!("{}", sum)
} else if radix == 16 {
n = format!("{:x}", sum)
} else if radix == 8 {
n = format!("{:0}", sum)

Осмичното форматиране не е с 0, а е със o. Това е грешка, която ще излезе само при рекурсивно извикване с поне 2 цифри, понеже ако е само една валидна осмична, ще се форматира по същия начин в десетична и в осмична система. Ударил си неприятен edge case, basically.

Yup. Добре си се погрижил да напишеш тестове, но не си успял да покриеш този случай. То и официалните тестове са малко basic, но изглежда сме те хванали :).

} else {
n = format!("{:b}", sum)
}
find_digital_root(n.as_str(), radix)
}
#[test]
fn test_basic() {
assert_eq!(decimal("345"), Some(3));
assert_eq!(hex("345"), Some(0xc));
assert_eq!(octal("1"), Some(1));
assert_eq!(binary("1"), Some(1));
let num = String::from("1");
assert_eq!(binary(&num[..]), Some(1));
}
#[test]
fn test_decimal() {
assert_eq!(decimal(""), None);
assert_eq!(decimal("0"), Some(0));
assert_eq!(decimal("00"), Some(0));
assert_eq!(decimal("01"), Some(1));
assert_eq!(decimal("baba"), None);
assert_eq!(decimal("-23"), None);
assert_eq!(decimal("9"), Some(9));
assert_eq!(decimal("55"), Some(1));
assert_eq!(decimal("11"), Some(2));
}
#[test]
fn test_hex() {
assert_eq!(hex(""), None);
assert_eq!(hex("0"), Some(0));
assert_eq!(hex("00"), Some(0));
assert_eq!(hex("01"), Some(1));
assert_eq!(hex("dqdo"), None);
assert_eq!(hex("-23"), None);
assert_eq!(hex("-f"), None);
assert_eq!(hex("deadbeef"), Some(14));
assert_eq!(hex("a"), Some(10));
assert_eq!(hex("b"), Some(11));
}
#[test]
fn test_octal() {
assert_eq!(octal(""), None);
assert_eq!(octal("0"), Some(0));
assert_eq!(octal("00"), Some(0));
assert_eq!(octal("01"), Some(1));
assert_eq!(octal("dqdo"), None);
assert_eq!(octal("-23"), None);
assert_eq!(octal("-f"), None);
assert_eq!(octal("deadbeef"), None);
assert_eq!(octal("10"), Some(1));
assert_eq!(octal("11"), Some(2));
}
#[test]
fn test_binary() {
assert_eq!(binary(""), None);
assert_eq!(binary("0"), Some(0));
assert_eq!(binary("01"), Some(1));
assert_eq!(binary("dqdo"), None);
assert_eq!(binary("-23"), None);
assert_eq!(binary("-f"), None);
assert_eq!(binary("deadbeef"), None);
assert_eq!(binary("00"), Some(0));
assert_eq!(binary("1"), Some(1));
assert_eq!(binary("10"), Some(1));
assert_eq!(binary("11"), Some(1));
assert_eq!(binary("110"), Some(1));
assert_eq!(binary("101"), Some(1));
assert_eq!(binary("111"), Some(1));
assert_eq!(binary("1011"), Some(1));
}

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

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

running 5 tests
test test_basic ... ok
test test_binary ... ok
test test_decimal ... ok
test test_hex ... ok
test test_octal ... ok

test result: ok. 5 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 ... FAILED
test solution_test::test_zeroes ... ok

failures:

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


failures:
    solution_test::test_octal_basic

test result: FAILED. 5 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

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

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

Дойчин качи първо решение на 02.11.2019 17:13 (преди почти 6 години)

Дойчин качи решение на 02.11.2019 17:29 (преди почти 6 години)

use std::string::String;
/// Десетична бройна система: 0-9
pub fn decimal(input: &str) -> Option<u32> {
find_digital_root(input, 10)
}
/// Шестнадесетична бройна система: 0-9, последвано от a-f
pub fn hex(input: &str) -> Option<u32> {
find_digital_root(input, 16)
}
/// Осмична бройна система: 0-7
pub fn octal(input: &str) -> Option<u32> {
find_digital_root(input, 8)
}
/// Двоична бройна система: 0-1
pub fn binary(input: &str) -> Option<u32> {
find_digital_root(input, 2)
}
fn find_digital_root(input: &str, radix: u32) -> Option<u32> {
if input.len() < 1 {
return None
}
if input.len() == 1 {
return input.chars().next().unwrap().to_digit(radix);
}

Може да заместиш тези две if-клаузи, използвайки оператора ?:

if input.len() <= 1 {
    return input.chars().next()?.to_digit(radix);
}

Дали е добра идея -- зависи. С две отделни if-клаузи стават малко по-ясни различните два случая. Въпросчето по средата на реда може освен това да се изгуби малко, така че ако не друго, може би поне бих направил това:

if input.len() <= 1 {
    let only_char = input.chars().next()?;
    return only_char.to_digit(radix);
}
let mut sum: u32 = 0;
for ch in input.chars() {
match ch.to_digit(radix) {
None => return None,
Some(v) => sum += v,
};
}
let n: String;
if radix == 10 {
n = format!("{}", sum)
} else if radix == 16 {
n = format!("{:x}", sum)
} else if radix == 8 {
n = format!("{:0}", sum)

Осмичното форматиране не е с 0, а е със o. Това е грешка, която ще излезе само при рекурсивно извикване с поне 2 цифри, понеже ако е само една валидна осмична, ще се форматира по същия начин в десетична и в осмична система. Ударил си неприятен edge case, basically.

Yup. Добре си се погрижил да напишеш тестове, но не си успял да покриеш този случай. То и официалните тестове са малко basic, но изглежда сме те хванали :).

} else {
n = format!("{:b}", sum)
}
find_digital_root(n.as_str(), radix)
}
#[test]
fn test_basic() {
assert_eq!(decimal("345"), Some(3));
assert_eq!(hex("345"), Some(0xc));
assert_eq!(octal("1"), Some(1));
assert_eq!(binary("1"), Some(1));
let num = String::from("1");
assert_eq!(binary(&num[..]), Some(1));
}
#[test]
fn test_decimal() {
assert_eq!(decimal(""), None);
+ assert_eq!(decimal("0"), Some(0));
+ assert_eq!(decimal("00"), Some(0));
+ assert_eq!(decimal("01"), Some(1));
assert_eq!(decimal("baba"), None);
assert_eq!(decimal("-23"), None);
assert_eq!(decimal("9"), Some(9));
assert_eq!(decimal("55"), Some(1));
assert_eq!(decimal("11"), Some(2));
+}
+
+#[test]
+fn test_hex() {
+ assert_eq!(hex(""), None);
+ assert_eq!(hex("0"), Some(0));
+ assert_eq!(hex("00"), Some(0));
+ assert_eq!(hex("01"), Some(1));
+ assert_eq!(hex("dqdo"), None);
+ assert_eq!(hex("-23"), None);
+ assert_eq!(hex("-f"), None);
+ assert_eq!(hex("deadbeef"), Some(14));
+ assert_eq!(hex("a"), Some(10));
+ assert_eq!(hex("b"), Some(11));
+}
+
+
+#[test]
+fn test_octal() {
+ assert_eq!(octal(""), None);
+ assert_eq!(octal("0"), Some(0));
+ assert_eq!(octal("00"), Some(0));
+ assert_eq!(octal("01"), Some(1));
+ assert_eq!(octal("dqdo"), None);
+ assert_eq!(octal("-23"), None);
+ assert_eq!(octal("-f"), None);
+ assert_eq!(octal("deadbeef"), None);
+ assert_eq!(octal("10"), Some(1));
+ assert_eq!(octal("11"), Some(2));
+}
+
+
+#[test]
+fn test_binary() {
+ assert_eq!(binary(""), None);
+ assert_eq!(binary("0"), Some(0));
+ assert_eq!(binary("01"), Some(1));
+ assert_eq!(binary("dqdo"), None);
+ assert_eq!(binary("-23"), None);
+ assert_eq!(binary("-f"), None);
+ assert_eq!(binary("deadbeef"), None);
+ assert_eq!(binary("00"), Some(0));
+ assert_eq!(binary("1"), Some(1));
+ assert_eq!(binary("10"), Some(1));
+ assert_eq!(binary("11"), Some(1));
+ assert_eq!(binary("110"), Some(1));
+ assert_eq!(binary("101"), Some(1));
+ assert_eq!(binary("111"), Some(1));
+ assert_eq!(binary("1011"), Some(1));
}

Не бяхме преподали оператора ? за домашното, но ако решиш да го приложиш, може 1-2 места да се посъкратят. Иначе, освен проблема с осмичното конвертиране, чудесно решение.