RosettaCodeData/Task/IBAN/Free-Pascal-Lazarus/iban.pas
2023-07-01 13:44:08 -04:00

81 lines
2.2 KiB
ObjectPascal
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{$mode objFPC}
uses
// for delSpace function
strUtils,
// GNU multiple-precision library
GMP;
var
/// this trie contains the correct IBAN length depending on the country code
IBANLengthInCountry: array['A'..'Z', 'A'..'Z'] of integer;
type
/// Human-readable representation of an IBAN without spaces
IBANRepresentation = string[34];
{
determines whether an IBANRepresentation is technically potentially correct
\param sample the human-readable IBAN representation
\return \param sample constains less than the most detectable errors
}
function isLegal(sample: IBANRepresentation): Boolean;
function checksumCorrect(sample: IBANRepresentation): Boolean;
type
digitSequence = string[68];
function convertLetters(const sequence: IBANRepresentation): digitSequence;
var
i: integer;
transliteration: string[2];
begin
// initialize length to zero
result := '';
for i := 1 to length(sequence) do
begin
// by default assume it is a Western-Arabic digit
transliteration := sequence[i];
// otherwise well need to transliterate the Latin alphabet character
if not (sequence[i] in ['0'..'9']) then
begin
writeStr(transliteration, ord(sequence[i]) - ord('A') + 10);
end;
// appending transliteration to result also changes the length field
result := result + transliteration;
end;
end;
var
i, k: MPInteger;
begin
k := 97;
// put first four characters toward end
writeStr(sample, sample[5..length(sample)], sample[1..4]);
// interpret converted string as integer to base 10
Z_set_str(i, convertLetters(sample), 10);
i := Z_mod(i, k);
k := 1;
checksumCorrect := Z_cmp(i, k) = 0;
end;
begin
sample := upCase(sample);
{$push}
// just for emphasis: by default the FPC performs lazy evaluation
{$boolEval off}
isLegal := (length(sample) = IBANLengthInCountry[sample[1], sample[2]])
and checksumCorrect(sample);
{$pop}
end;
// === MAIN ==============================================================
begin
// for the sake of merely achieving the Rosetta Code Task
IBANLengthInCountry['G', 'B'] := 22;
// note, strings longer than 34 characters will be silently clipped
writeLn(isLegal(delSpace('GB82 WEST 1234 5698 7654 32')));
end.