Luhn From

1. Readme

来自 Luhn

Luhn:使用 From Trait

在做这个练习之前,你应该做原始的 LuHn 练习。如果您还没有完成 Luhn,您可以通过运行命令来获得它:

exercism download --exercise=luhn --track=rust

在原始的 LuHn 练习中,您只验证字符串,但 Luhn 算法也可以应用于整数。

在本练习中,您将实现From trait,用来将字符串、strs 和无符号整数转换为执行验证的结构。

资源

The Rust track maintainers,基于原始 Luhn 练习

2. 开始你的表演

pub struct Luhn;

impl Luhn {
   pub fn is_valid(&self) -> bool {
       unimplemented!("Determine if the current Luhn struct contains a valid credit card number.");
   }
}

/// Here is the example of how the From trait could be implemented
/// for the &str type. Naturally, you can implement this trait
/// by hand for the every other type presented in the test suite,
/// but your solution will fail if a new type is presented.
/// Perhaps there exists a better solution for this problem?
impl<'a> From<&'a str> for Luhn {
   fn from(input: &'a str) -> Self {
       unimplemented!("From the given input '{}' create a new Luhn struct.", input);
   }
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
#[test]
fn you_can_validate_from_a_str() {
   let valid = Luhn::from("046 454 286");
   let invalid = Luhn::from("046 454 287");
   assert!(valid.is_valid());
   assert!(!invalid.is_valid());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_string() {
   let valid = Luhn::from(String::from("046 454 286"));
   let invalid = Luhn::from(String::from("046 454 287"));
   assert!(valid.is_valid());
   assert!(!invalid.is_valid());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_u8() {
   let valid = Luhn::from(240u8);
   let invalid = Luhn::from(241u8);
   assert!(valid.is_valid());
   assert!(!invalid.is_valid());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_u16() {
   let valid = Luhn::from(64_436u16);
   let invalid = Luhn::from(64_437u16);
   assert!(valid.is_valid());
   assert!(!invalid.is_valid());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_u32() {
   let valid = Luhn::from(46_454_286u32);
   let invalid = Luhn::from(46_454_287u32);
   assert!(valid.is_valid());
   assert!(!invalid.is_valid());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_u64() {
   let valid = Luhn::from(8273_1232_7352_0562u64);
   let invalid = Luhn::from(8273_1232_7352_0569u64);
   assert!(valid.is_valid());
   assert!(!invalid.is_valid());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_usize() {
   let valid = Luhn::from(8273_1232_7352_0562usize);
   let invalid = Luhn::from(8273_1232_7352_0569usize);
   assert!(valid.is_valid());
   assert!(!invalid.is_valid());
}

#[test]
//#[ignore]
fn single_digit_string_is_invalid() {
   assert!(!Luhn::from("1").is_valid());
}

#[test]
//#[ignore]
fn single_zero_string_is_invalid() {
   assert!(!Luhn::from("0").is_valid());
}

#[test]
//#[ignore]
fn valid_canadian_sin_is_valid() {
   assert!(Luhn::from("046 454 286").is_valid());
}

#[test]
//#[ignore]
fn invalid_canadian_sin_is_invalid() {
   assert!(!Luhn::from("046 454 287").is_valid());
}

#[test]
//#[ignore]
fn invalid_credit_card_is_invalid() {
   assert!(!Luhn::from("8273 1232 7352 0569").is_valid());
}

#[test]
//#[ignore]
fn strings_that_contain_non_digits_are_invalid() {
   assert!(!Luhn::from("046a 454 286").is_valid());
}

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
pub struct Luhn {
   digits: Vec<char>,
}

impl Luhn {
   pub fn is_valid(&self) -> bool {
       if self.digits.iter().any(|c| c.is_alphabetic()) || self.digits.iter().count() == 1 {
           return false;
       }

       self.digits
           .iter()
           .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::<u32>() % 10 == 0
   }
}

impl From<String> for Luhn {
   fn from(s: String) -> Self {
       Luhn {
           digits: s.chars().collect(),
       }
   }
}

impl<'a> From<&'a str> for Luhn {
   fn from(s: &'a str) -> Self {
       Luhn::from(String::from(s))
   }
}

impl From<u8> for Luhn {
   fn from(s: u8) -> Self {
       Luhn::from(s.to_string())
   }
}

impl From<u16> for Luhn {
   fn from(s: u16) -> Self {
       Luhn::from(s.to_string())
   }
}

impl From<u32> for Luhn {
   fn from(s: u32) -> Self {
       Luhn::from(s.to_string())
   }
}

impl From<u64> for Luhn {
   fn from(s: u64) -> Self {
       Luhn::from(s.to_string())
   }
}

impl From<usize> for Luhn {
   fn from(s: usize) -> Self {
       Luhn::from(s.to_string())
   }
}

#}



填充/相关