Re: Credit Card numbers as syntactic data type

Here is a better version.

The previous version worked from right to left, because the Luhn
algorithm works from right to left, numbering the digits from the
right. So to know whether you should double a digit, you need to know
if it is odd or even numbered from the right.

The new version however works from left to right. So how does it know
if a digit is to be doubled or not? It doesn't. Instead, it does both,
but a string that begins with a doubled digit has to have an even
number of digits, so that it ends with a singled digit, and a string
that starts with a singled digit has to have an odd number of digits,
likewise.

So "s0" matches an odd number of characters that add up to a multiple
of 10 following the Luhn algorithm, and "d0" matches an even number of
characters that match the Luhn algorithm.

Here is the left to right version, this time announcing if a number
matches the Luhn constraint or not (followed by an example of its
output):

{this version works from left to right}
input: try++-#a, -#a.
  -try: good; bad.
  good: s0; d0.
   bad: ^s1; ^d1; ^s2; ^d2; ^s3; ^d3; ^s4; ^d4; ^s5; ^d5; ^s6; ^d6; ^s7; 
^d7; ^s8; ^d8; ^s9; ^d9.

-s0: "0", d0; "1", d1; "2", d2; "3", d3; "4", d4; "5", d5; "6", d6; "7", 
d7; "8", d8; "9", d9.
-d0: "0", s0; "1", s2; "2", s4; "3", s6; "4", s8; "5", s1; "6", s3; "7", 
s5; "8", s7; "9", s9; .

-s1: "0", d1; "1", d2; "2", d3; "3", d4; "4", d5; "5", d6; "6", d7; "7", 
d8; "8", d9; "9", d0.
-d1: "0", s1; "1", s3; "2", s5; "3", s7; "4", s9; "5", s2; "6", s4; "7", 
s6; "8", s8; "9", s0.

-s2: "0", d2; "1", d3; "2", d4; "3", d5; "4", d6; "5", d7; "6", d8; "7", 
d9; "8", d0; "9", d1.
-d2: "0", s2; "1", s4; "2", s6; "3", s8; "4", s0; "5", s3; "6", s5; "7", 
s7; "8", s9; "9", s1.

-s3: "0", d3; "1", d4; "2", d5; "3", d6; "4", d7; "5", d8; "6", d9; "7", 
d0; "8", d1; "9", d2.
-d3: "0", s3; "1", s5; "2", s7; "3", s9; "4", s1; "5", s4; "6", s6; "7", 
s8; "8", s0; "9", s2.

-s4: "0", d4; "1", d5; "2", d6; "3", d7; "4", d8; "5", d9; "6", d0; "7", 
d1; "8", d2; "9", d3.
-d4: "0", s4; "1", s6; "2", s8; "3", s0; "4", s2; "5", s5; "6", s7; "7", 
s9; "8", s1; "9", s3.

-s5: "0", d5; "1", d6; "2", d7; "3", d8; "4", d9; "5", d0; "6", d1; "7", 
d2; "8", d3; "9", d4.
-d5: "0", s5; "1", s7; "2", s9; "3", s1; "4", s3; "5", s6; "6", s8; "7", 
s0; "8", s2; "9", s4.

-s6: "0", d6; "1", d7; "2", d8; "3", d9; "4", d0; "5", d1; "6", d2; "7", 
d3; "8", d4; "9", d5.
-d6: "0", s6; "1", s8; "2", s0; "3", s2; "4", s4; "5", s7; "6", s9; "7", 
s1; "8", s3; "9", s5.

-s7: "0", d7; "1", d8; "2", d9; "3", d0; "4", d1; "5", d2; "6", d3; "7", 
d4; "8", d5; "9", d6.
-d7: "0", s7; "1", s9; "2", s1; "3", s3; "4", s5; "5", s8; "6", s0; "7", 
s2; "8", s4; "9", s6.

-s8: "0", d8; "1", d9; "2", d0; "3", d1; "4", d2; "5", d3; "6", d4; "7", 
d5; "8", d6; "9", d7.
-d8: "0", s8; "1", s0; "2", s2; "3", s4; "4", s6; "5", s9; "6", s1; "7", 
s3; "8", s5; "9", s7.

-s9: "0", d9; "1", d0; "2", d1; "3", d2; "4", d3; "5", d4; "6", d5; "7", 
d6; "8", d7; "9", d8.
-d9: "0", s9; "1", s1; "2", s3; "3", s5; "4", s7; "5", s0; "6", s2; "7", 
s4; "8", s6; "9", s8.

======


<input>
    <bad>
       <d3>3141592653589793</d3>
    </bad>
    <good>3141592653589796</good>
    <bad>
       <d4>1414213562373095</d4>
    </bad>
    <good>1414213562373099</good>
    <bad>
       <s4>141421356237309</s4>
    </bad>
    <bad>
       <s4>14142135623730991</s4>
    </bad>
    <good>0</good>
    <good>00</good>
    <good>000</good>
    <bad>
       <s9>1</s9>
    </bad>
    <good>34</good>
    <good>133</good>
    <good>1330133</good>
    <good>01330133</good>
</input>

Steven

Received on Thursday, 28 August 2025 16:53:14 UTC