2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -23,12 +23,13 @@
|
|||
;; a built in function to verify for alphanumeric characters, but it includes characters beyond ASCII range.
|
||||
;;
|
||||
(defun IBAN-characters (iban)
|
||||
(flet ((valid-alphanum (ch) (or (and (char<= #\A ch) (char>= #\Z ch)) (and (char<= #\0 ch) (char>= #\9 ch)))))
|
||||
(loop :for char :across iban
|
||||
:finally (return t)
|
||||
:do
|
||||
(when (not (valid-alphanum char))
|
||||
(return nil)))))
|
||||
(flet ((valid-alphanum (ch)
|
||||
(or (and (char<= #\A ch)
|
||||
(char>= #\Z ch))
|
||||
(and (char<= #\0 ch)
|
||||
(char>= #\9 ch)))))
|
||||
(loop for char across iban
|
||||
always (valid-alphanum char))))
|
||||
|
||||
;;
|
||||
;; The function IBAN-length verifies that the length of the number is correct. The code lengths
|
||||
|
|
|
|||
36
Task/IBAN/Elixir/iban.elixir
Normal file
36
Task/IBAN/Elixir/iban.elixir
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
defmodule IBAN do
|
||||
@len %{ AL: 28, AD: 24, AT: 20, AZ: 28, BE: 16, BH: 22, BA: 20, BR: 29,
|
||||
BG: 22, CR: 21, HR: 21, CY: 28, CZ: 24, DK: 18, DO: 28, EE: 20,
|
||||
FO: 18, FI: 18, FR: 27, GE: 22, DE: 22, GI: 23, GR: 27, GL: 18,
|
||||
GT: 28, HU: 28, IS: 26, IE: 22, IL: 23, IT: 27, KZ: 20, KW: 30,
|
||||
LV: 21, LB: 28, LI: 21, LT: 20, LU: 20, MK: 19, MT: 31, MR: 27,
|
||||
MU: 30, MC: 27, MD: 24, ME: 22, NL: 18, NO: 15, PK: 24, PS: 29,
|
||||
PL: 28, PT: 25, RO: 24, SM: 27, SA: 24, RS: 22, SK: 24, SI: 19,
|
||||
ES: 24, SE: 24, CH: 21, TN: 24, TR: 26, AE: 23, GB: 22, VG: 24 }
|
||||
|
||||
def valid?(iban) do
|
||||
iban = String.replace(iban, ~r/\s/, "")
|
||||
if Regex.match?(~r/^[\dA-Z]+$/, iban) do
|
||||
cc = String.slice(iban, 0..1) |> String.to_atom
|
||||
if String.length(iban) == @len[cc] do
|
||||
{left, right} = String.split_at(iban, 4)
|
||||
num = String.codepoints(right <> left)
|
||||
|> Enum.map_join(fn c -> String.to_integer(c,36) end)
|
||||
|> String.to_integer
|
||||
rem(num,97) == 1
|
||||
else
|
||||
false
|
||||
end
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
[ "GB82 WEST 1234 5698 7654 32",
|
||||
"gb82 west 1234 5698 7654 32",
|
||||
"GB82 WEST 1234 5698 7654 320",
|
||||
"GB82WEST12345698765432",
|
||||
"GB82 TEST 1234 5698 7654 32",
|
||||
"ZZ12 3456 7890 1234 5678 12" ]
|
||||
|> Enum.each(fn iban -> IO.puts "#{IBAN.valid?(iban)}\t#{iban}" end)
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import Data.Char (toUpper)
|
||||
import Data.Maybe (fromJust)
|
||||
|
||||
validateIBAN :: String -> Either String String
|
||||
validateIBAN [] = Left "No IBAN number."
|
||||
|
|
@ -38,12 +39,9 @@ validateIBAN xs =
|
|||
-- convert the letters to numbers and
|
||||
-- convert the result to an integer
|
||||
p4 :: Integer
|
||||
p4 = read $ concat $ convertLetters p3
|
||||
convertLetters [] = []
|
||||
convertLetters (x:xs)
|
||||
| x `elem` digits = [x] : convertLetters xs
|
||||
| otherwise = let (Just ys) = lookup x replDigits
|
||||
in ys : convertLetters xs
|
||||
p4 = read $ concat $ map convertLetter p3
|
||||
convertLetter x | x `elem` digits = [x]
|
||||
| otherwise = fromJust $ lookup x replDigits
|
||||
-- see if the number is valid
|
||||
check = if sane
|
||||
then if p4 `mod` 97 == 1
|
||||
|
|
|
|||
27
Task/IBAN/JavaScript/iban.js
Normal file
27
Task/IBAN/JavaScript/iban.js
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
var ibanLen = {
|
||||
NO:15, BE:16, DK:18, FI:18, FO:18, GL:18, NL:18, MK:19,
|
||||
SI:19, AT:20, BA:20, EE:20, KZ:20, LT:20, LU:20, CR:21,
|
||||
CH:21, HR:21, LI:21, LV:21, BG:22, BH:22, DE:22, GB:22,
|
||||
GE:22, IE:22, ME:22, RS:22, AE:23, GI:23, IL:23, AD:24,
|
||||
CZ:24, ES:24, MD:24, PK:24, RO:24, SA:24, SE:24, SK:24,
|
||||
VG:24, TN:24, PT:25, IS:26, TR:26, FR:27, GR:27, IT:27,
|
||||
MC:27, MR:27, SM:27, AL:28, AZ:28, CY:28, DO:28, GT:28,
|
||||
HU:28, LB:28, PL:28, BR:29, PS:29, KW:30, MU:30, MT:31
|
||||
}
|
||||
|
||||
function isValid(iban) {
|
||||
iban = iban.replace(/\s/g, '')
|
||||
if (!iban.match(/^[\dA-Z]+$/)) return false
|
||||
var len = iban.length
|
||||
if (len != ibanLen[iban.substr(0,2)]) return false
|
||||
iban = iban.substr(4) + iban.substr(0,4)
|
||||
for (var s='', i=0; i<len; i+=1) s+=parseInt(iban.charAt(i),36)
|
||||
for (var m=s.substr(0,15)%97, s=s.substr(15); s; s=s.substr(13)) m=(m+s.substr(0,13))%97
|
||||
return m == 1
|
||||
}
|
||||
|
||||
document.write(isValid('GB82 WEST 1234 5698 7654 32'), '<br>') // true
|
||||
document.write(isValid('GB82 WEST 1.34 5698 7654 32'), '<br>') // false
|
||||
document.write(isValid('GB82 WEST 1234 5698 7654 325'), '<br>') // false
|
||||
document.write(isValid('GB82 TEST 1234 5698 7654 32'), '<br>') // false
|
||||
document.write(isValid('SA03 8000 0000 6080 1016 7519'), '<br>') // true
|
||||
24
Task/IBAN/Lua/iban.lua
Normal file
24
Task/IBAN/Lua/iban.lua
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
local length=
|
||||
{
|
||||
AL=28, AD=24, AT=20, AZ=28, BH=22, BE=16, BA=20, BR=29, BG=22, CR=21,
|
||||
HR=21, CY=28, CZ=24, DK=18, DO=28, EE=20, FO=18, FI=18, FR=27, GE=22,
|
||||
DE=22, GI=23, GR=27, GL=18, GT=28, HU=28, IS=26, IE=22, IL=23, IT=27,
|
||||
JO=30, KZ=20, KW=30, LV=21, LB=28, LI=21, LT=20, LU=20, MK=19, MT=31,
|
||||
MR=27, MU=30, MC=27, MD=24, ME=22, NL=18, NO=15, PK=24, PS=29, PL=28,
|
||||
PT=25, QA=29, RO=24, SM=27, SA=24, RS=22, SK=24, SI=19, ES=24, SE=24,
|
||||
CH=21, TN=24, TR=26, AE=23, GB=22, VG=24
|
||||
}
|
||||
|
||||
function validate(iban)
|
||||
iban=iban:gsub("%s","")
|
||||
local l=length[iban:sub(1,2)]
|
||||
if not l or l~=#iban or iban:match("[^%d%u]") then
|
||||
return false -- invalid character, country code or length
|
||||
end
|
||||
local mod=0
|
||||
local rotated=iban:sub(5)..iban:sub(1,4)
|
||||
for c in rotated:gmatch(".") do
|
||||
mod=(mod..tonumber(c,36)) % 97
|
||||
end
|
||||
return mod==1
|
||||
end
|
||||
106
Task/IBAN/OCaml/iban.ocaml
Normal file
106
Task/IBAN/OCaml/iban.ocaml
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#load "str.cma"
|
||||
#load "nums.cma" (* for module Big_int *)
|
||||
|
||||
|
||||
(* Countries and length of their IBAN. *)
|
||||
(* Taken from https://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country *)
|
||||
let countries = [
|
||||
("AL", 28); ("AD", 24); ("AT", 20); ("AZ", 28); ("BH", 22); ("BE", 16);
|
||||
("BA", 20); ("BR", 29); ("BG", 22); ("CR", 21); ("HR", 21); ("CY", 28);
|
||||
("CZ", 24); ("DK", 18); ("DO", 28); ("TL", 23); ("EE", 20); ("FO", 18);
|
||||
("FI", 18); ("FR", 27); ("GE", 22); ("DE", 22); ("GI", 23); ("GR", 27);
|
||||
("GL", 18); ("GT", 28); ("HU", 28); ("IS", 26); ("IE", 22); ("IL", 23);
|
||||
("IT", 27); ("JO", 30); ("KZ", 20); ("XK", 20); ("KW", 30); ("LV", 21);
|
||||
("LB", 28); ("LI", 21); ("LT", 20); ("LU", 20); ("MK", 19); ("MT", 31);
|
||||
("MR", 27); ("MU", 30); ("MC", 27); ("MD", 24); ("ME", 22); ("NL", 18);
|
||||
("NO", 15); ("PK", 24); ("PS", 29); ("PL", 28); ("PT", 25); ("QA", 29);
|
||||
("RO", 24); ("SM", 27); ("SA", 24); ("RS", 22); ("SK", 24); ("SI", 19);
|
||||
("ES", 24); ("SE", 24); ("CH", 21); ("TN", 24); ("TR", 26); ("AE", 23);
|
||||
("GB", 22); ("VG", 24); ("DZ", 24); ("AO", 25); ("BJ", 28); ("BF", 27);
|
||||
("BI", 16); ("CM", 27); ("CV", 25); ("IR", 26); ("CI", 28); ("MG", 27);
|
||||
("ML", 28); ("MZ", 25); ("SN", 28); ("UA", 29)
|
||||
]
|
||||
(* Put the countries in a Hashtbl for faster search... *)
|
||||
let tbl_countries =
|
||||
let htbl = Hashtbl.create (List.length countries) in
|
||||
let _ = List.iter (fun (k, v) -> Hashtbl.add htbl k v) countries in
|
||||
htbl
|
||||
|
||||
|
||||
(* Delete spaces and put all letters in upper case. *)
|
||||
let clean_iban iban =
|
||||
Str.global_replace (Str.regexp " +") "" iban
|
||||
|> String.uppercase_ascii
|
||||
|
||||
|
||||
(* Each country has an IBAN with a specific length. *)
|
||||
let check_length ib =
|
||||
let iso_length = List.hd countries |> fst |> String.length in
|
||||
let country_code = String.sub ib 0 iso_length in
|
||||
try
|
||||
Hashtbl.find tbl_countries country_code = String.length ib
|
||||
with
|
||||
Not_found -> false
|
||||
|
||||
|
||||
(* Convert a string into a list of chars. *)
|
||||
let charlist_of_string s =
|
||||
let l = String.length s in
|
||||
let rec doloop i =
|
||||
if i >= l then []
|
||||
else s.[i] :: doloop (i + 1)
|
||||
in
|
||||
doloop 0
|
||||
|
||||
|
||||
(* Letters are associated to values: A=10, B=11, ..., Z=35. *)
|
||||
let val_of_char c =
|
||||
match c with
|
||||
| '0' .. '9' -> int_of_char c - int_of_char '0'
|
||||
| 'A' .. 'Z' -> int_of_char c - int_of_char 'A' + 10
|
||||
| _ -> failwith (Printf.sprintf "Character not allowed: %c" c)
|
||||
|
||||
|
||||
(* Compute the mod-97 value and check it is equal to 1. *)
|
||||
let check_mod97 ib =
|
||||
let l = String.length ib
|
||||
and taken = 4 in
|
||||
let prefix = String.sub ib 0 taken
|
||||
and rest = String.sub ib taken (l - taken) in
|
||||
let newval = rest ^ prefix (* move the 4 initial characters to the end of the string *)
|
||||
|> charlist_of_string (* convert the string into a list of chars *)
|
||||
|> List.map val_of_char (* convert each char into its integer value *)
|
||||
|> List.map string_of_int (* convert the integers into strings... *)
|
||||
|> List.fold_left (^) "" in (* ...and concatenate said strings *)
|
||||
(* Now compute the mod-97 using the Big Integers provided by OCaml, and
|
||||
* compare the result to 1. *)
|
||||
Big_int.eq_big_int
|
||||
(Big_int.mod_big_int (Big_int.big_int_of_string newval)
|
||||
(Big_int.big_int_of_int 97))
|
||||
(Big_int.big_int_of_int 1)
|
||||
|
||||
|
||||
(* Do the validation as described in the Wikipedia article at
|
||||
* https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN *)
|
||||
let validate iban =
|
||||
let ib = clean_iban iban in
|
||||
check_length ib && check_mod97 ib
|
||||
|
||||
|
||||
let () =
|
||||
let ibans = [
|
||||
("GB82 WEST 1234 5698 7654 32", true);
|
||||
("GB82 TEST 1234 5698 7654 32", false);
|
||||
("GB81 WEST 1234 5698 7654 32", false);
|
||||
("GB82 WEST 1234 5698 7654 3", false);
|
||||
("SA03 8000 0000 6080 1016 7519", true);
|
||||
("CH93 0076 2011 6238 5295 7", true);
|
||||
("\"Completely incorrect iban\"", false)
|
||||
] in
|
||||
let testit (ib, exp) =
|
||||
let res = validate ib in
|
||||
Printf.printf "%s is %svalid. Expected %b [%s]\n"
|
||||
ib (if res then "" else "not ")
|
||||
exp (if res = exp then "PASS" else "FAIL")
|
||||
in
|
||||
List.iter (fun pair -> testit pair) ibans
|
||||
60
Task/IBAN/PowerShell/iban-1.psh
Normal file
60
Task/IBAN/PowerShell/iban-1.psh
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
@'
|
||||
"Country","Length","Example"
|
||||
"Albania",28,"AL47212110090000000235698741"
|
||||
"Andorra",24,"AD1200012030200359100100"
|
||||
"Austria",20,"AT611904300235473201"
|
||||
"Belgium",16,"BE68539007547034"
|
||||
"Bosnia and Herzegovina",20,"BA391290079401028494"
|
||||
"Bulgaria",22,"BG80BNBG96611020345678"
|
||||
"Croatia",21,"HR1210010051863000160"
|
||||
"Cyprus",28,"CY17002001280000001200527600"
|
||||
"Czech Republic",24,"CZ6508000000192000145399"
|
||||
"Denmark",18,"DK5000400440116243"
|
||||
"Estonia",20,"EE382200221020145685"
|
||||
"Faroe Islands",18,"FO1464600009692713"
|
||||
"Finland",18,"FI2112345600000785"
|
||||
"France",27,"FR1420041010050500013M02606"
|
||||
"Georgia",22,"GE29NB0000000101904917"
|
||||
"Germany",22,"DE89370400440532013000"
|
||||
"Gibraltar",23,"GI75NWBK000000007099453"
|
||||
"Greece",27,"GR1601101250000000012300695"
|
||||
"Greenland",18,"GL8964710001000206"
|
||||
"Hungary",28,"HU42117730161111101800000000"
|
||||
"Iceland",26,"IS140159260076545510730339"
|
||||
"Ireland",22,"IE29AIBK93115212345678"
|
||||
"Italy",27,"IT60X0542811101000000123456"
|
||||
"Kosovo",20,"XK051212012345678906"
|
||||
"Latvia",21,"LV80BANK0000435195001"
|
||||
"Liechtenstein",21,"LI21088100002324013AA"
|
||||
"Lithuania",20,"LT121000011101001000"
|
||||
"Luxembourg",20,"LU280019400644750000"
|
||||
"Macedonia",19,"MK07300000000042425"
|
||||
"Malta",31,"MT84MALT011000012345MTLCAST001S"
|
||||
"Moldova",24,"MD24AG000225100013104168"
|
||||
"Monaco",27,"MC5813488000010051108001292"
|
||||
"Montenegro",22,"ME25505000012345678951"
|
||||
"Netherlands",18,"NL91ABNA0417164300"
|
||||
"Norway",15,"NO9386011117947"
|
||||
"Poland",28,"PL27114020040000300201355387"
|
||||
"Portugal",25,"PT50000201231234567890154"
|
||||
"Romania",24,"RO49AAAA1B31007593840000"
|
||||
"San Marino",27,"SM86U0322509800000000270100"
|
||||
"Serbia",22,"RS35260005601001611379"
|
||||
"Slovakia",24,"SK3112000000198742637541"
|
||||
"Slovenia",19,"SI56191000000123438"
|
||||
"Spain",24,"ES9121000418450200051332"
|
||||
"Sweden",24,"SE3550000000054910000003"
|
||||
"Switzerland",21,"CH9300762011623852957"
|
||||
"Ukraine",29,"UA573543470006762462054925026"
|
||||
"United Kingdom",22,"GB29NWBK60161331926819"
|
||||
'@ -split "`r`n" | Set-Content -Path .\IBAN.csv -Force
|
||||
|
||||
$ibans = foreach ($iban in Import-Csv -Path .\IBAN.csv)
|
||||
{
|
||||
$iban | Select-Object -Property Country,
|
||||
@{Name='Code' ; Expression={$iban.Example.Substring(0,2)}},
|
||||
@{Name='Length'; Expression={[int]$iban.Length}},
|
||||
Example
|
||||
}
|
||||
|
||||
$ibans
|
||||
10
Task/IBAN/PowerShell/iban-2.psh
Normal file
10
Task/IBAN/PowerShell/iban-2.psh
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
$regex = [regex]'[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{6}[0-9]{5}([a-zA-Z0-9]?){0,16}'
|
||||
|
||||
foreach ($iban in $ibans)
|
||||
{
|
||||
[PSCustomObject]@{
|
||||
Country = $iban.Country
|
||||
Example = $iban.Example
|
||||
IsValid = $regex.IsMatch($iban.Example)
|
||||
}
|
||||
}
|
||||
81
Task/IBAN/SNOBOL4/iban.sno
Normal file
81
Task/IBAN/SNOBOL4/iban.sno
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
* IBAN - International Bank Account Number validation
|
||||
DEFINE('ibantable()') :(iban_table_end)
|
||||
ibantable
|
||||
ibantable = TABLE(70)
|
||||
ibancodes =
|
||||
+ 'AL28AD24AT20AZ28BE16BH22BA20BR29BG22CR21'
|
||||
+ 'HR21CY28CZ24DK18DO28EE20FO18FI18FR27GE22'
|
||||
+ 'DE22GI23GR27GL18GT28HU28IS26IE22IL23IT27'
|
||||
+ 'KZ20KW30LV21LB28LI21LT20LU20MK19MT31MR27'
|
||||
+ 'MU30MC27MD24ME22NL18NO15PK24PS29PL28PT25'
|
||||
+ 'RO24SM27SA24RS22SK24SI19ES24SE24CH21TN24'
|
||||
+ 'TR26AE23GB22VG24'
|
||||
nordeacodes =
|
||||
+ 'DZ24AO25BJ28FB27BI16CM27CV25IR26CI28MG27'
|
||||
+ 'ML28MZ25SN28UA29'
|
||||
allcodes = ibancodes nordeacodes
|
||||
iban1 allcodes LEN(2) . country LEN(2) . length = :F(return)
|
||||
ibantable<country> = length :(iban1)
|
||||
iban_table_end
|
||||
|
||||
DEFINE('tonumbers(tonumbers)letter,p') :(tonumbers_end)
|
||||
tonumbers
|
||||
tonumbers ANY(&UCASE) . letter :f(RETURN)
|
||||
&UCASE @p letter
|
||||
tonumbers letter = p + 10 :(tonumbers)
|
||||
tonumbers_end
|
||||
|
||||
* modulo for long integers
|
||||
*
|
||||
DEFINE('mod(m,n)') :(mod_end)
|
||||
mod m LEN(9) . r = :f(modresult)
|
||||
mod = REMDR(CONVERT(r,"INTEGER"), n)
|
||||
mod0 m LEN(7) . r = :f(modresult)
|
||||
mod = mod r
|
||||
mod = REMDR(mod, n) :(mod0)
|
||||
modresult
|
||||
mod = GT(SIZE(m), 0) REMDR(mod m, n) :(RETURN)
|
||||
mod_end
|
||||
|
||||
DEFINE('invalid(l,t)') :(invalid_end)
|
||||
invalid
|
||||
OUTPUT = "Invalid IBAN: " l ": " t :(RETURN)
|
||||
invalid_end
|
||||
|
||||
***** main *****
|
||||
ibant = ibantable()
|
||||
FREEZE(ibant)
|
||||
|
||||
INPUT(.INPUT, 28,,'iban.dat')
|
||||
read line = INPUT :f(END)
|
||||
country = checkdigits = line2 =
|
||||
** GB82 WEST 1234 5698 7654 32
|
||||
** Uppercase line2 and remove spaces.
|
||||
line2 = REPLACE(line, &LCASE, &UCASE)
|
||||
space line2 ANY(" ") = :s(space)
|
||||
|
||||
** GB82WEST12345698765432
|
||||
** Capture country code and checkdigits.
|
||||
line2 LEN(2) . country LEN(2) . checkdigits
|
||||
|
||||
** 1. Is the country code known?
|
||||
IDENT(ibant<country>)
|
||||
+ invalid(line, "unlisted country: " country) :s(read)
|
||||
|
||||
** 2. Is the length correct for the country?
|
||||
NE(SIZE(line2), ibant<country>)
|
||||
+ invalid(line, "length: " SIZE(line2)
|
||||
+ " not " ibant<country>) :s(read)
|
||||
|
||||
** 3. Move first four chars to end of line.
|
||||
** Convert line2 letters to numbers.
|
||||
** 3214282912345698765432161182
|
||||
line2 = SUBSTR(line2,5) SUBSTR(line2,1,4)
|
||||
line2 = tonumbers(line2)
|
||||
** Mod_97 of line2 = 1?
|
||||
modsum = mod(line2, 97)
|
||||
NE(modsum, 1)
|
||||
+ invalid(line, "mod_97 " modsum " not = 1") :s(read)
|
||||
|
||||
OUTPUT = "valid IBAN: " line :(read)
|
||||
END
|
||||
Loading…
Add table
Add a link
Reference in a new issue