Rebol3 Code Examplex


Luhn test of credit card numbers

Validate numbers with the Luhn checksum.

Rebol [
    title: "Rosetta code: Luhn test of credit card numbers"
    file:  %Luhn_test_of_credit_card_numbers.r3
    url:   https://rosettacode.org/wiki/Luhn_test_of_credit_card_numbers
]

luhn?: function [
    "Luhn algorithm validator - returns true/false if a number passes the Luhn check."
    "Used to validate credit card numbers and other identification numbers."
    num [integer! string!]
][
    sum: 0
    ;; Define a character set matching only numeric digits '0' through '9'
    digit: system/catalog/bitsets/numeric

    ;; Reverse the string so we process digits right-to-left, as Luhn requires.
    parse reverse form num [
        ;; SOME means "match the following pattern one or more times"
        some [
            ;; --- ODD position digits (1st, 3rd, 5th... from the right) ---
            set num: digit (
                ;; Convert char to integer by subtracting ASCII value of '0'
                ;; and add directly to sum (odd-position digits are unchanged)
                sum: sum + num - #"0"
            )
            ;; --- EVEN position digits (2nd, 4th, 6th... from the right) ---
            opt [set num: digit (
                ;; Double the digit (after converting char to integer)
                num: 2 * (num - #"0")
                ;; If doubling gives > 9, subtract 9 (equivalent to summing the
                ;; two digits of the result, e.g. 14 -> 1+4=5, same as 14-9=5)
                if num > 9 [num: num - 9]
                ;; Add the adjusted even-position digit to the running sum
                sum: sum + num
            )]
        ]
    ]
    ;; Return true if total sum is divisible by 10 (Luhn check passes)
    zero? sum % 10
]

foreach num [49927398716 49927398717 1234567812345678 1234567812345670][
    print [num 'is pick [valid invalid] luhn? num "number."]
]