Luhn Trait

1. Readme

鲁恩 trait

Luhn: 使用自定义 trait

在做这个练习之前,你应该做原始的 luhn 练习和进阶练习,”luhn:使用 From trait”.

要获得原始的 Luhn 练习,运行

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

要获得”Lunn:使用 From trait”的练习,运行

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

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

在”Lurn:使用 From trait”中,你实现了一个 From trait,还需要你创建一个 luhn 结构。

要是不创建一个结构来执行验证呢,如果要您自己验证了原语本身(即,String,u8 等)呢?

在本练习中,您将创建并实现自定义trait,来执行验证.

注:它是实现原语的 trait,不是 Rust 的习惯。 在这个练习中,我们展示了一些你可以做的东西,而不是你应该做的东西。如果你发现自己在原语上实现了 trait,也许你有一个Primitive Obsession例子。

资源

基于原始 luhn 练习,延续 Rust 轨迹

2. 开始你的表演

pub trait Luhn {
   fn valid_luhn(&self) -> bool;
}

/// Here is the example of how to implement custom Luhn trait
/// 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> Luhn for &'a str {
   fn valid_luhn(&self) -> bool {
       unimplemented!("Determine if '{}' is a valid credit card number.", self);
   }
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
#[test]
fn you_can_validate_from_a_str() {
   assert!("046 454 286".valid_luhn());
   assert!(!"046 454 287".valid_luhn());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_string() {
   assert!(String::from("046 454 286").valid_luhn());
   assert!(!String::from("046 454 287").valid_luhn());
}

#[test]
//#[ignore]
fn you_can_validate_from_a_u8() {
   assert!(240u8.valid_luhn());
   assert!(!241u8.valid_luhn());
}

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

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

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

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

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
pub trait Luhn {
   fn valid_luhn(&self) -> bool;
}

impl Luhn for String {
   fn valid_luhn(&self) -> bool {
       if self.chars().any(|c| c.is_alphabetic()) || self.chars().count() == 1 {
           return false;
       }

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

impl<'a> Luhn for &'a str {
   fn valid_luhn(&self) -> bool {
       String::from(*self).valid_luhn()
   }
}

impl Luhn for u8 {
   fn valid_luhn(&self) -> bool {
       self.to_string().valid_luhn()
   }
}

impl Luhn for u16 {
   fn valid_luhn(&self) -> bool {
       self.to_string().valid_luhn()
   }
}

impl Luhn for u32 {
   fn valid_luhn(&self) -> bool {
       self.to_string().valid_luhn()
   }
}

impl Luhn for u64 {
   fn valid_luhn(&self) -> bool {
       self.to_string().valid_luhn()
   }
}

impl Luhn for usize {
   fn valid_luhn(&self) -> bool {
       self.to_string().valid_luhn()
   }
}

#}



填充/相关