diff --git a/config.json b/config.json index d42737d53..aaec8e669 100644 --- a/config.json +++ b/config.json @@ -122,6 +122,15 @@ "match" ] }, + { + "slug": "luhn", + "difficulty": 1, + "topics": [ + "str to digits", + "iterators", + "higher-order functions" + ] + }, { "slug": "largest-series-product", "difficulty": 1, diff --git a/exercises/luhn/.gitignore b/exercises/luhn/.gitignore new file mode 100644 index 000000000..0e49cdd58 --- /dev/null +++ b/exercises/luhn/.gitignore @@ -0,0 +1,7 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock \ No newline at end of file diff --git a/exercises/luhn/Cargo.toml b/exercises/luhn/Cargo.toml new file mode 100644 index 000000000..6dc3dff8d --- /dev/null +++ b/exercises/luhn/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "luhn" +version = "0.0.0" diff --git a/exercises/luhn/example.rs b/exercises/luhn/example.rs new file mode 100644 index 000000000..da6c35021 --- /dev/null +++ b/exercises/luhn/example.rs @@ -0,0 +1,13 @@ +pub fn is_valid(candidate: &str) -> bool { + if candidate.chars().any(|c| c.is_alphabetic()) || candidate.chars().count() == 1 { + return false; + } + + candidate.chars() + .filter_map(|c| c.to_digit(10)) + .rev() + .enumerate() + .map(|(index, digit)| if index % 2 == 0 { digit } else { digit * 2 }) + .map(|digit| if digit > 9 { digit - 9 } else { digit }) + .sum::() % 10 == 0 +} diff --git a/exercises/luhn/tests/luhn.rs b/exercises/luhn/tests/luhn.rs new file mode 100644 index 000000000..bcf809e5e --- /dev/null +++ b/exercises/luhn/tests/luhn.rs @@ -0,0 +1,38 @@ +extern crate luhn; + +use luhn::*; + +#[test] +fn single_digit_string_is_invalid() { + assert!(!is_valid("1")); +} + +#[test] +#[ignore] +fn single_zero_string_is_invalid() { + assert!(!is_valid("0")); +} + +#[test] +#[ignore] +fn valid_canadian_sin_is_valid() { + assert!(is_valid("046 454 286")); +} + +#[test] +#[ignore] +fn invalid_canadian_sin_is_invalid() { + assert!(!is_valid("046 454 287")); +} + +#[test] +#[ignore] +fn invalid_credit_card_is_invalid() { + assert!(!is_valid("8273 1232 7352 0569")); +} + +#[test] +#[ignore] +fn strings_that_contain_non_digits_are_invalid() { + assert!(!is_valid("046a 454 286")); +}