

 This page uses content from Wikipedia. The original article was at IBAN. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)



The   International Bank Account Number (IBAN)   is an internationally agreed means of identifying bank accounts across national borders with a reduced risk of propagating transcription errors.

The IBAN consists of up to 34 alphanumeric characters:

   first the two-letter ISO 3166-1 alpha-2 country code, 
   then two check digits, and 
   finally a country-specific Basic Bank Account Number (BBAN). 


The check digits enable a sanity check of the bank account number to confirm its integrity even before submitting a transaction.



Task

Validate the following fictitious IBAN:    GB82 WEST 1234 5698 7654 32 



Details of the algorithm can be found on the Wikipedia page.




on countryCodes()
    -- A list of 34 lists. The nth list (1-indexed) contains country codes for countries having n-character IBANS.
    return {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {"NO"}, {"BE"}, ¬
        {}, {"DK", "FO", "FI", "GL", "NL"}, {"MK", "SI"}, {"AT", "BA", "EE", "KZ", "XK", "LT", "LU"}, ¬
        {"HR", "LV", "LI", "CH"}, {"BH", "BG", "CR", "GE", "DE", "IE", "ME", "RS", "GB", "VA"}, ¬
        {"TL", "GI", "IQ", "IL", "AE"}, {"AD", "CZ", "MD", "PK", "RO", "SA", "SK", "ES", "SE", "TN", "VG"}, ¬
        {"PT", "ST"}, {"IS", "TR"}, {"FR", "GR", "IT", "MR", "MC", "SM"}, ¬
        {"AL", "AZ", "BY", "CY", "DO", "SV", "GT", "HU", "LB", "PL"}, {"BR", "EG", "PS", "QA", "UA"}, ¬
        {"JO", "KW", "MU"}, {"MT", "SC"}, {"LC"}, {}, {}}
end countryCodes
 
on validateIBAN(iban)
    -- Remove any spaces.
    if (iban contains space) then set iban to replaceText(iban, space, "")
    considering diacriticals but ignoring case
        -- Check the length both overall and against the presumed country code.
        set characterCount to (count iban)
        if ((characterCount > 34) or (text 1 thru 2 of iban is not in item characterCount of countryCodes())) then return false
        -- Move the first four characters to the end.
        set iban to text 5 thru -1 of iban & (text 1 thru 4 of iban)
        -- Replace any unadorned Latin letters with the appropriate number characters ("A" = "11" … "Z" = "35").
        repeat with letter in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            if (iban contains letter) then set iban to replaceText(iban, letter, ((letter's id) mod 32 + 9) as text)
        end repeat
    end considering
    -- Check that what's left only contains digit characters.
    if (replaceText(iban, characters of "0123456789", "") is not "") then return false
    -- Calculate the mod-97 remainder.
    set characterCount to (count iban)
    set c to (characterCount - 1) mod 7 + 1
    set mod97 to (text 1 thru c of iban) mod 97
    repeat with c from (c + 1) to characterCount by 7
        set mod97 to (mod97 * 10000000 + (text c thru (c + 6) of iban)) mod 97
    end repeat
 
    return (mod97 = 1)
end validateIBAN
 
on replaceText(txt, searchStr, replaceText)
    set astid to AppleScript's text item delimiters
    set AppleScript's text item delimiters to searchStr
    set txt to txt's text items
    set AppleScript's text item delimiters to replaceText
    set txt to txt as text
    set AppleScript's text item delimiters to astid
    return txt
end replaceText
 
-- Test code (IBANs borrowed from other solutions on this page.):
local testIBANs, output, thisIBAN, astid
 
set testIBANs to {"GB82 WEST 1234 5698 7654 32", "gb82 west 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32", ¬
    "SA03 8000 0000 6080 1016 7519", "ZZ12 3456 7890 1234 5678 12", "IL62 0108 0000 0009 9999 999"}
set output to {}
repeat with thisIBAN in testIBANs
    set end of output to thisIBAN & item ((validateIBAN(thisIBAN) as integer) + 1) of {":  invalid", ":  valid"}
end repeat
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed
set output to output as text
set AppleScript's text item delimiters to astid
return output