81 lines
2.2 KiB
ObjectPascal
81 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.
|