ISBN Verifier

1. Readme

ISBN 检验器

这个ISBN-10 检测进程用于验证图书识别号。通常包含破折号,看起来像:3-598-21508-8

国际标准书号

ISBN-10 格式是 9 位数字(0 到 9)加上一个校验字符(一个数字或一个 X)。在校验字符为 X 的情况下,这表示值”10”。这些可以与连字符(不管有没有)通信,并且可以通过以下公式检查它们的有效性:

(x1 * 10 + x2 * 9 + x3 * 8 + x4 * 7 + x5 * 6 + x6 * 5 + x7 * 4 + x8 * 3 + x9 * 2 + x10 * 1) mod 11 == 0

如果结果是 0,那么它是一个有效的 ISBN-10,否则它是无效的.

例子

让我们用 ISBN-103-598-21508-8. 我们把它插入到公式中,得到:

(3 * 10 + 5 * 9 + 9 * 8 + 8 * 7 + 2 * 6 + 1 * 5 + 5 * 4 + 0 * 3 + 8 * 2 + 8 * 1) mod 11 == 0

由于结果是 0,这证明我们的 ISBN 是有效的.

任务

给定一个字符串,程序应该检查所提供的字符串是否是有效的 ISBN-10。为了实现这一点,需要在计算 ISBN 的校验位数之前,考虑字符串的预处理/解析.

该程序应该能够验证 ISBN-10 的破折号(不管有没有).

告诫

在某些语言中,从字符串转换为数字可能是棘手的。现在,甚至更棘手的是,ISBN-10 的校验位可能是”X”(表示”10”).例如3-598-21507-X是一个有效的 ISBN-10.

奖金任务

  • 从输入 ISBN-10 生成有效的 ISBN-13(并且可能用类似验证器再次验证它).

  • 生成有效的 ISBN,甚至可能从给定的起始 ISBN 中生成.

资源

将一个字符串,转换成一个数字和一些基本的处理,利用一个可靠的真实世界的例子.https://en.wikipedia.org/wiki/International_Standard_Book_Number#ISBN-10_check_digit_calculation

2. 开始你的表演

/// Determines whether the supplied string is a valid ISBN number
pub fn is_valid_isbn(isbn: &str) -> bool {
   unimplemented!("Is {:?} a valid ISBN number?", isbn);
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
#[test]
fn test_valid() {
   assert!(is_valid_isbn("3-598-21508-8"));
}

#[test]
//#[ignore]
fn test_invalid_check_digit() {
   assert!(!is_valid_isbn("3-598-21508-9"));
}

#[test]
//#[ignore]
fn test_valid_check_digit_of_10() {
   assert!(is_valid_isbn("3-598-21507-X"));
}

#[test]
//#[ignore]
fn test_invalid_character_as_check_digit() {
   assert!(!is_valid_isbn("3-598-21507-A"));
}

#[test]
//#[ignore]
fn test_invalid_character_in_isbn() {
   assert!(!is_valid_isbn("3-598-2K507-0"));
}

#[test]
//#[ignore]
#[allow(non_snake_case)]
fn test_invalid_isbn_with_invalid_X() {
   assert!(!is_valid_isbn("3-598-2X507-9"));
}

#[test]
//#[ignore]
fn test_valid_isbn_without_dashes() {
   assert!(is_valid_isbn("3598215088"));
}

#[test]
//#[ignore]
#[allow(non_snake_case)]
fn test_valid_isbn_without_dashes_and_X_as_check() {
   assert!(is_valid_isbn("359821507X"));
}

#[test]
//#[ignore]
fn test_invalid_isbn_without_dashes_and_no_check_digit() {
   assert!(!is_valid_isbn("359821507"));
}

#[test]
//#[ignore]
fn test_invalid_isbn_without_dashes_and_too_long() {
   assert!(!is_valid_isbn("3598215078X"));
}

#[test]
//#[ignore]
fn test_invalid_isbn_without_check_digit() {
   assert!(!is_valid_isbn("3-598-21507"));
}

#[test]
//#[ignore]
fn test_invalid_isbn_too_long() {
   assert!(!is_valid_isbn("3-598-21507-XX"));
}

#[test]
//#[ignore]
fn test_valid_digits_invalid_length() {
   assert!(!is_valid_isbn("35982150881"));
}

#[test]
//#[ignore]
fn test_special_characters() {
   assert!(!is_valid_isbn("!@#%!@"));
}

#[test]
//#[ignore]
#[allow(non_snake_case)]
fn test_invalid_isbn_with_check_digit_X_instead_of_0() {
   assert!(!is_valid_isbn("3-598-21515-X"));
}

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
/// An ISBN type
#[derive(PartialEq, Eq)]
enum IsbnType {
   Isbn10,
   Isbn13,
}

/// Checks if an 'X' is valid at the given position for the given ISBN type
#[allow(non_snake_case)]
fn is_X_valid(position: &usize, isbn_type: &IsbnType) -> bool {
   (isbn_type == &IsbnType::Isbn10 && position == &9)
       || (isbn_type == &IsbnType::Isbn13 && position == &12)
}

/// Checks if a '-' is valid at the given position for the given ISBN type
fn is_dash_valid(position: &usize, isbn_type: &IsbnType) -> bool {
   isbn_type == &IsbnType::Isbn13 && (position == &1 || position == &5 || position == &11)
}

/// Determines whether the supplied string is a valid ISBN number
pub fn is_valid_isbn(isbn: &str) -> bool {
   let isbn_type = match isbn.len() {
       10 => IsbnType::Isbn10,
       13 => IsbnType::Isbn13,
       _ => return false,
   };

   let mut checksum = 0;
   let mut coefficient = 10;
   for (position, c) in isbn.char_indices() {
       let digit_value = match c {
           '0'...'9' => c.to_digit(10).unwrap(),
           'X' if is_X_valid(&position, &isbn_type) => 10,
           '-' if is_dash_valid(&position, &isbn_type) => continue,
           _ => return false,
       };

       checksum += coefficient * digit_value;
       coefficient -= 1;
   }

   checksum % 11 == 0
}

#}



填充/相关