Luhn test of credit card numbers: Difference between revisions

→‎Pascal: standardize [use ISO standards as basis], move code to [non-standardized] →‎Free Pascal
(Emacs Lisp: Remove cl.el use, simplify code)
(→‎Pascal: standardize [use ISO standards as basis], move code to [non-standardized] →‎Free Pascal)
Line 2,837:
1234567812345678 = FALSE
1234567812345670 = TRUE</pre>
 
=={{header|Free Pascal}}==
''see also: [[#Pascal|Pascal]]''
<lang Pascal>program luhn;
 
function lunh(arg: string): boolean;
var
i, sum: integer;
temp: byte;
begin
sum := 0;
for i:= length(arg) downto 1 do begin // Run the characters backwards
temp := byte(arg[i])-48; // Convert from ASCII to byte
if (length(arg)-i) mod 2 = 0
then sum := sum + temp // Odd characters just add
else if temp < 5
then sum := sum + 2*temp // Even characters add double
else sum := sum + (2*temp)-9; // or sum the digits of the doubling
end;
result := sum mod 10 = 0; // Return true if sum ends in a 0
end;
 
begin
writeln(' 49927398716: ', lunh('49927398716'));
writeln(' 49927398717: ', lunh('49927398717'));
writeln('1234567812345678: ', lunh('1234567812345678'));
writeln('1234567812345670: ', lunh('1234567812345670'));
end.</lang>
 
{{out}}
<pre> 49927398716: TRUE
49927398717: FALSE
1234567812345678: FALSE
1234567812345670: TRUE</pre>
 
=={{header|FunL}}==
Line 4,031 ⟶ 4,065:
 
=={{header|Pascal}}==
''see also: [[#Free Pascal|Free Pascal]]''
<lang Pascal>program luhn;
{{works with|Extended Pascal}}
This implementation skips the ''reversal'' step and simply reads the input backwards.
<lang Pascal>program luhnTestOfCreditCardNumbers(input, output);
 
type
function lunh(arg: string): boolean;
{
var
`string(…)` is an Extended Pascal, ISO 10206, extension.
i, sum: integer;
`string(64)` discriminates the “schema” data type `string`
temp: byte;
to contain at most 64 `char` values.
begin
}
sum := 0;
creditCardNumber = string(64);
for i:= length(arg) downto 1 do begin // Run the characters backwards
temp := byte(arg[i])-48; // Convert from ASCII to byte
if (length(arg)-i) mod 2 = 0
then sum := sum + temp // Odd characters just add
else if temp < 5
then sum := sum + 2*temp // Even characters add double
else sum := sum + (2*temp)-9; // or sum the digits of the doubling
end;
result := sum mod 10 = 0; // Return true if sum ends in a 0
end;
 
{
\brief determines whether a string contains digits only
\param sample the string to inspect
\return `false` iff `sample` contains non-digit characters
}
{ Extended Pascal: `protected` means the function cannot modify `sample` }
function containsDigitsOnly(protected sample: creditCardNumber): Boolean;
var
{ EP: the `… value []` initializes this variable as an empty set }
characters: set of char value [];
{ `sample.capacity` refers to `64` in this code. }
i: 1..sample.capacity;
begin
for i := 1 to length(sample) do
writeln(' 49927398716: ', lunh('49927398716'));
begin
writeln(' 49927398717: ', lunh('49927398717'));
{ Union of sets indicated by `+`. }
writeln('1234567812345678: ', lunh('1234567812345678'));
characters := characters + [sample[i]]
writeln('1234567812345670: ', lunh('1234567812345670'));
end;
{
In a Pascal `function` definition,
there must be one assignment to the (implicit) variable
bearing the same name as of the function.
This will be the return value.
}
{ NB: This will return `true` even if `length(sample)` is zero. }
containsDigitsOnly := card(characters - ['0'..'9']) = 0
{ `card` is an Extended Pascal extension. }
end;
 
{
\brief determines whether a string complies with ISO/IEC 7812-1 Luhn test
\param sample the potentially correct credit card number
\return `true` if verification succeeds
}
function luhnCheck(protected sample: creditCardNumber): Boolean;
{
This _nested_ function is only accessible _within_ `luhnCheck`.
Outsourcing this code allows us to write a neat expression below.
}
function check: Boolean;
var
{ Using `integer` sub-ranges ensures only these values are assigned. }
sum: 0..maxInt value 0;
i: 0..sample.capacity-1;
begin
for i := 0 to length(sample) - 1 do
begin
{ `1 + ord(odd(i))` produces an alternating scale factor `* 1`/`* 2`. }
sum := sum + (1 + ord(odd(i))) *
{ Obtain digit value for `integer` calculation. }
(ord(sample[length(sample) - i]) - ord('0')) -
{ Reverse operation if digit sum > 9, i.e. we added “too much”. }
ord(odd(i) and (sample[length(sample) - i] >= '5')) * 9
end;
check := sum mod 10 = 0
end;
begin
{
The Extended Pascal Boolean operator `and_then` (and `or_else`)
allows for “short-circuit evaluation”.
Otherwise, in Pascal `and` and `or` mandate complete evaluation.
}
luhnCheck := (length(sample) > 0) and_then containsDigitsOnly(sample)
and_then check
end;
 
{ === MAIN ============================================================= }
var
s: creditCardNumber;
begin
{ `EOF` is short for `EOF(input)`. }
while not EOF do
begin
readLn(s); { equivalent to `readLn(input, s)` }
writeLn(luhnCheck(s)) { = `writeLn(output, …)` }
end
end.</lang>
{{in}}
<pre>49927398716
49927398717
1234567812345678
1234567812345670</pre>
 
{{out}}
<pre>True
<pre> 49927398716: TRUE
False
49927398717: FALSE
False
1234567812345678: FALSE
1234567812345670: TRUETrue</pre>
The shown output was generated by a program compiled with the GPC, the [[GNU Pascal]] Compiler.
A different compiler may emit a different rendition of <tt>true</tt> and <tt>false</tt>, for example in all-caps.
 
=={{header|Perl}}==
149

edits