演習: Luhn アルゴリズム

Luhn algorithm は、クレジットカード番号を 検証するために使用されます。このアルゴリズムは文字列を入力として受け取り、クレジットカード番号を検証するために 次のことを行います。

  • すべての空白を無視します。2 桁未満の数字は拒否します。文字や その他の数字以外の文字は拒否します。

  • 右から左へ移動しながら、2 つおきの数字をすべて 2 倍します。数値 1234 では、31 を 2 倍します。数値 98765 では、68 を 2 倍します。

  • 数字を 2 倍した後、結果が 9 より大きい場合はその桁を合計します。したがって、 7 を 2 倍すると 14 になり、これは 1 + 4 = 5 になります。

  • 2 倍していない数字と 2 倍した数字をすべて合計します。

  • 合計が 0 で終わる場合、そのクレジットカード番号は有効です。

提供されているコードには、Luhn アルゴリズムのバグのある実装と、 アルゴリズムの大部分が正しく実装されていることを確認する 2 つの基本的なユニットテストが 含まれています。

以下のコードを https://play.rust-lang.org/ にコピーし、追加のテストを作成して 提供されている実装のバグを明らかにし、見つけたバグを修正してください。

// 著作権 2023 Google LLC
// SPDX-License-Identifier: Apache-2.0

pub fn luhn(cc_number: &str) -> bool {
    let mut sum = 0;
    let mut double = false;

    for c in cc_number.chars().rev() {
        if let Some(digit) = c.to_digit(10) {
            if double {
                let double_digit = digit * 2;
                sum +=
                    if double_digit > 9 { double_digit - 9 } else { double_digit };
            } else {
                sum += digit;
            }
            double = !double;
        } else {
            continue;
        }
    }

    sum % 10 == 0
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_valid_cc_number() {
        assert!(luhn("4263 9826 4026 9299"));
        assert!(luhn("4539 3195 0343 6467"));
        assert!(luhn("7992 7398 713"));
    }

    #[test]
    fn test_invalid_cc_number() {
        assert!(!luhn("4223 9826 4026 9299"));
        assert!(!luhn("4539 3195 0343 6476"));
        assert!(!luhn("8273 1232 7352 0569"));
    }
}