82 lines
2.2 KiB
ObjectPascal
82 lines
2.2 KiB
ObjectPascal
|
|
{$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 we’ll 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.
|