September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,8 +1,20 @@
|
|||
{{wikipedia}}
|
||||
The [[wp:International_Bank_Account_Number|International Bank Account Number (IBAN)]] is an internationally agreed means of identifying bank accounts across national borders with a reduced risk of propagating [[wp:Transcription_error|transcription errors]]. <br>
|
||||
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). <br>
|
||||
|
||||
|
||||
The [[wp:International_Bank_Account_Number|International Bank Account Number (IBAN)]] is an internationally agreed means of identifying bank accounts across national borders with a reduced risk of propagating [[wp:Transcription_error|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.
|
||||
|
||||
The task here is to validate the following fictitious IBAN: <tt>GB82 WEST 1234 5698 7654 32</tt>.
|
||||
|
||||
;Task:
|
||||
Validate the following fictitious IBAN: <tt> GB82 WEST 1234 5698 7654 32 </tt>
|
||||
|
||||
|
||||
Details of the algorithm can be found on the Wikipedia page.
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -2,36 +2,40 @@ import java.math.BigInteger;
|
|||
import java.util.*;
|
||||
|
||||
public class IBAN {
|
||||
static final Map<String, Integer> isoPairs;
|
||||
|
||||
static final String iso = "AL28 AD24 AT20 AZ28 BE16 BH22 BA20 BR29 BG22 "
|
||||
private static final String DEFSTRS = ""
|
||||
+ "AL28 AD24 AT20 AZ28 BE16 BH22 BA20 BR29 BG22 "
|
||||
+ "HR21 CY28 CZ24 DK18 DO28 EE20 FO18 FI18 FR27 GE22 DE22 GI23 "
|
||||
+ "GL18 GT28 HU28 IS26 IE22 IL23 IT27 KZ20 KW30 LV21 LB28 LI21 "
|
||||
+ "LT20 LU20 MK19 MT31 MR27 MU30 MC27 MD24 ME22 NL18 NO15 PK24 "
|
||||
+ "PS29 PL28 PT25 RO24 SM27 SA24 RS22 SK24 SI19 ES24 SE24 CH21 "
|
||||
+ "TN24 TR26 AE23 GB22 VG24 GR27 CR21";
|
||||
private static final Map<String, Integer> DEFINITIONS = new HashMap<>();
|
||||
|
||||
static {
|
||||
isoPairs = new HashMap<>();
|
||||
for (String p : iso.split(" "))
|
||||
isoPairs.put(p.substring(0, 2), Integer.parseInt(p.substring(2)));
|
||||
for (String definition : DEFSTRS.split(" "))
|
||||
DEFINITIONS.put(definition.substring(0, 2), Integer.parseInt(definition.substring(2)));
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (String iban : new String[]{"GB82 WEST 1234 5698 7654 32",
|
||||
"GB82 TEST 1234 5698 7654 32",
|
||||
"GB81 WEST 1234 5698 7654 32",
|
||||
"SA03 8000 0000 6080 1016 7519",
|
||||
"CH93 0076 2011 6238 5295 7"})
|
||||
System.out.printf("%s is valid: %s%n%n", iban, validateIBAN(iban));
|
||||
String[] ibans = {
|
||||
"GB82 WEST 1234 5698 7654 32",
|
||||
"GB82 TEST 1234 5698 7654 32",
|
||||
"GB81 WEST 1234 5698 7654 32",
|
||||
"SA03 8000 0000 6080 1016 7519",
|
||||
"CH93 0076 2011 6238 5295 7",
|
||||
"XX00 0000",
|
||||
"",
|
||||
"DE",
|
||||
"DE13 äöü_ 1234 1234 1234 12"};
|
||||
for (String iban : ibans)
|
||||
System.out.printf("%s is %s.%n", iban, validateIBAN(iban) ? "valid" : "not valid");
|
||||
}
|
||||
|
||||
static boolean validateIBAN(String iban) {
|
||||
iban = iban.replaceAll("\\s", "").toUpperCase();
|
||||
iban = iban.replaceAll("\\s", "").toUpperCase(Locale.ROOT);
|
||||
|
||||
int len = iban.length();
|
||||
|
||||
if (len < 4 || isoPairs.get(iban.substring(0, 2)) != len)
|
||||
if (len < 4 || !iban.matches("[0-9A-Z]+") || DEFINITIONS.getOrDefault(iban.substring(0, 2), 0) != len)
|
||||
return false;
|
||||
|
||||
iban = iban.substring(4) + iban.substring(0, 4);
|
||||
|
|
@ -42,6 +46,6 @@ public class IBAN {
|
|||
|
||||
BigInteger bigInt = new BigInteger(sb.toString());
|
||||
|
||||
return bigInt.mod(new BigInteger("97")).intValue() == 1;
|
||||
return bigInt.mod(BigInteger.valueOf(97)).intValue() == 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
28
Task/IBAN/Julia/iban.julia
Normal file
28
Task/IBAN/Julia/iban.julia
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# v0.6.0
|
||||
function validiban(iban::String)
|
||||
const COUNTRY2LENGTH = Dict(
|
||||
"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
|
||||
)
|
||||
|
||||
# Ensure upper alphanumeric input.
|
||||
iban = replace(iban, " ", "")
|
||||
iban = replace(iban, "\t", "")
|
||||
|
||||
rst = ismatch(r"^[\dA-Z]+$", iban)
|
||||
# Validate country code against expected length.
|
||||
rst = rst && length(iban) == COUNTRY2LENGTH[iban[1:2]]
|
||||
# Shift and convert.
|
||||
iban = iban[5:end] * iban[1:4]
|
||||
digits = parse(BigInt, join(string(parse(Int, ch, 36)) for ch in iban))
|
||||
return rst && digits % 97 == 1
|
||||
end
|
||||
|
||||
@show validiban("GB82 WEST 1234 5698 7654 32")
|
||||
@show validiban("GB82 TEST 1234 5698 7654 32")
|
||||
40
Task/IBAN/Kotlin/iban.kotlin
Normal file
40
Task/IBAN/Kotlin/iban.kotlin
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// version 1.0.6
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
object Iban {
|
||||
/* List updated to release 73, January 2017, of IBAN Registry (75 countries) */
|
||||
private val countryCodes =
|
||||
"AD24 AE23 AL28 AT20 AZ28 BA20 BE16 BG22 BH22 BR29 BY28 CH21 CR22 CY28 CZ24 DE22 " +
|
||||
"DK18 DO28 EE20 ES24 FI18 FO18 FR27 GB22 GE22 GI23 GL18 GR27 GT28 HR21 HU28 IE22 " +
|
||||
"IL23 IQ23 IS26 IT27 JO30 KW30 KZ20 LB28 LC32 LI21 LT20 LU20 LV21 MC27 MD24 ME22 " +
|
||||
"MK19 MR27 MT31 MU30 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 RS22 SA24 SC31 SE24 " +
|
||||
"SI19 SK24 SM27 ST25 SV28 TL23 TN24 TR26 UA29 VG24 XK20"
|
||||
|
||||
private fun checkCountryCode(cc: String) = cc in countryCodes
|
||||
|
||||
fun validate(iban: String): Boolean {
|
||||
// remove spaces from IBAN
|
||||
var s = iban.replace(" ", "")
|
||||
|
||||
// check country code
|
||||
if (!checkCountryCode(s.substring(0, 2) + s.length)) return false
|
||||
|
||||
// move first 4 characters to end
|
||||
s = s.substring(4) + s.substring(0, 4)
|
||||
|
||||
// replace A to Z with numbers 10 To 35
|
||||
for (ch in 'A'..'Z') s = s.replace(ch.toString(), (ch - 55).toInt().toString())
|
||||
|
||||
// check whether mod 97 calculation gives a remainder of 1
|
||||
return BigInteger(s) % BigInteger.valueOf(97L) == BigInteger.ONE
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val ibans = arrayOf("GB82 WEST 1234 5698 7654 32", "GB82 TEST 1234 5698 7654 32")
|
||||
for (iban in ibans) {
|
||||
val isValid = Iban.validate(iban)
|
||||
println(iban + if(isValid) " may be valid" else " is not valid")
|
||||
}
|
||||
}
|
||||
59
Task/IBAN/Phix/iban.phix
Normal file
59
Task/IBAN/Phix/iban.phix
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
--
|
||||
-- demo\rosetta\IBAN.exw
|
||||
-- =====================
|
||||
--
|
||||
constant nations = {{"AD",24}, -- Andorra
|
||||
-- (full list in distro)
|
||||
{"CH",21}, -- Switzerland
|
||||
{"GB",22}, -- United Kingdom
|
||||
{"SA",24}, -- Saudi Arabia
|
||||
{"XK",20}} -- Kosovo
|
||||
|
||||
constant {countries,lengths} = columnize(nations)
|
||||
|
||||
function iban(string code)
|
||||
-- This routine does and should reject codes containing spaces etc.
|
||||
-- Use iban_s() below for otherwise.
|
||||
integer country = find(code[1..2],countries)
|
||||
if country!=0
|
||||
and length(code)=lengths[country] then
|
||||
code = code[5..$]&code[1..4]
|
||||
integer c = 0
|
||||
for i=1 to length(code) do
|
||||
integer ch=code[i]
|
||||
if ch>='0' and ch<='9' then
|
||||
c = c*10+ch-'0'
|
||||
elsif ch>='A' and ch<='Z' then
|
||||
c = c*100+ch-55
|
||||
else
|
||||
return false
|
||||
end if
|
||||
c = mod(c,97)
|
||||
end for
|
||||
return c=1
|
||||
end if
|
||||
return false
|
||||
end function
|
||||
|
||||
function iban_s(string code)
|
||||
-- strips any embedded spaces and hyphens before validating.
|
||||
code = substitute_all(code,{" ","-"},{"",""})
|
||||
return iban(code)
|
||||
end function
|
||||
|
||||
procedure test(string code, bool expected)
|
||||
bool valid = iban_s(code)
|
||||
string state
|
||||
if valid=expected then
|
||||
state = iff(valid?"ok":"invalid (as expected)")
|
||||
else
|
||||
state = iff(valid?"OK!!":"INVALID!!")&" (NOT AS EXPECTED)"
|
||||
end if
|
||||
printf(1,"%-34s :%s\n",{code,state})
|
||||
end procedure
|
||||
|
||||
test("GB82 WEST 1234 5698 7654 32",true)
|
||||
test("GB82 TEST 1234 5698 7654 32",false)
|
||||
test("GB81 WEST 1234 5698 7654 32",false)
|
||||
test("SA03 8000 0000 6080 1016 7519",true)
|
||||
test("CH93 0076 2011 6238 5295 7",true)
|
||||
65
Task/IBAN/Rust/iban.rust
Normal file
65
Task/IBAN/Rust/iban.rust
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
fn main() {
|
||||
for iban in [
|
||||
"",
|
||||
"x",
|
||||
"QQ82",
|
||||
"QQ82W",
|
||||
"GB82 TEST 1234 5698 7654 322",
|
||||
"gb82 WEST 1234 5698 7654 32",
|
||||
"GB82 WEST 1234 5698 7654 32",
|
||||
"GB82 TEST 1234 5698 7654 32",
|
||||
"GB81 WEST 1234 5698 7654 32",
|
||||
"SA03 8000 0000 6080 1016 7519",
|
||||
"CH93 0076 2011 6238 5295 7",
|
||||
].iter()
|
||||
{
|
||||
println!(
|
||||
"'{}' is {}valid",
|
||||
iban,
|
||||
if validate_iban(iban) { "" } else { "NOT " }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_iban(iban: &str) -> bool {
|
||||
let iso_len = [
|
||||
("AL", 28), ("AD", 24), ("AT", 20), ("AZ", 28), ("BE", 16), ("BH", 22),
|
||||
("BA", 20), ("BR", 29), ("BG", 22), ("HR", 21), ("CY", 28), ("CZ", 24),
|
||||
("DK", 18), ("DO", 28), ("EE", 20), ("FO", 18), ("FI", 18), ("FR", 27),
|
||||
("GE", 22), ("DE", 22), ("GI", 23), ("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), ("GR", 27), ("CR", 21),
|
||||
];
|
||||
let trimmed_iban = iban.chars()
|
||||
.filter(|&ch| ch != ' ')
|
||||
.collect::<String>()
|
||||
.to_uppercase();
|
||||
if trimmed_iban.len() < 4 {
|
||||
return false;
|
||||
}
|
||||
let prefix = &trimmed_iban[0..2];
|
||||
if let Some(pair) = iso_len.iter().find(|&&(code, _)| code == prefix) {
|
||||
if pair.1 != trimmed_iban.len() {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
let reversed_iban = format!("{}{}", &trimmed_iban[4..], &trimmed_iban[0..4]);
|
||||
let mut expanded_iban = String::new();
|
||||
for ch in reversed_iban.chars() {
|
||||
expanded_iban.push_str(&if ch.is_numeric() {
|
||||
format!("{}", ch)
|
||||
} else {
|
||||
format!("{}", ch as u8 - 'A' as u8 + 10u8)
|
||||
});
|
||||
}
|
||||
expanded_iban.bytes().fold(0, |acc, ch| {
|
||||
(acc * 10 + ch as u32 - '0' as u32) % 97
|
||||
}) == 1
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
func valid_iban(iban) {
|
||||
static len = Hash.new(
|
||||
static len = Hash(
|
||||
AD=>24, AE=>23, AL=>28, AO=>25, AT=>20, AZ=>28, BA=>20, BE=>16, BF=>27,
|
||||
BG=>22, BH=>22, BI=>16, BJ=>28, BR=>29, CG=>27, CH=>21, CI=>28, CM=>27,
|
||||
CR=>21, CV=>25, CY=>28, CZ=>24, DE=>22, DK=>18, DO=>28, DZ=>24, EE=>20,
|
||||
|
|
@ -10,22 +10,22 @@ func valid_iban(iban) {
|
|||
MZ=>25, NL=>18, NO=>15, PK=>24, PL=>28, PS=>29, PT=>25, QA=>29, RO=>24,
|
||||
RS=>22, SA=>24, SE=>24, SI=>19, SK=>24, SM=>27, SN=>28, TN=>24, TR=>26,
|
||||
UA=>29, VG=>24,
|
||||
);
|
||||
)
|
||||
|
||||
# Ensure upper alphanumeric input.
|
||||
iban -= /\s+/g;
|
||||
iban.uc! ~~ /^[0-9A-Z]+\z/ || return false;
|
||||
iban -= /\s+/g
|
||||
iban.uc! ~~ /^[0-9A-Z]+\z/ || return false
|
||||
|
||||
# Validate country code against expected length.
|
||||
var cc = iban.substr(0, 2);
|
||||
iban.len == len{cc} || return false;
|
||||
var cc = iban.substr(0, 2)
|
||||
iban.len == len{cc} || return false
|
||||
|
||||
# Shift and convert.
|
||||
iban.sub!(/(.{4})(.+)/, {|a,b| b+a});
|
||||
iban.gsub!(/([A-Z])/, {|a| a.ord - 55});
|
||||
iban.sub!(/(.{4})(.+)/, {|a,b| b+a})
|
||||
iban.gsub!(/([A-Z])/, {|a| a.ord - 55})
|
||||
|
||||
iban.to_i % 97 == 1;
|
||||
iban.to_i % 97 == 1
|
||||
}
|
||||
|
||||
say valid_iban("GB82 WEST 1234 5698 7654 32"); #=> true
|
||||
say valid_iban("GB82 TEST 1234 5698 7654 32"); #=> false
|
||||
say valid_iban("GB82 WEST 1234 5698 7654 32") #=> true
|
||||
say valid_iban("GB82 TEST 1234 5698 7654 32") #=> false
|
||||
|
|
|
|||
67
Task/IBAN/Standard-ML/iban.ml
Normal file
67
Task/IBAN/Standard-ML/iban.ml
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
(* country_code : string -> int *)
|
||||
(* Get the length of a valid IBAN given the two chars long country code *)
|
||||
fun country_code (str : string) : int =
|
||||
case str of
|
||||
"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
|
||||
| _ => raise Domain
|
||||
|
||||
|
||||
(* removespace : string -> string *)
|
||||
(* Removes all spaces from a string *)
|
||||
fun removespace s = String.translate (fn #" " => "" | c => str c) s
|
||||
|
||||
(* to_upper : string -> string *)
|
||||
(* Convert every char to upper of a string *)
|
||||
fun to_upper (s : string) : string =
|
||||
String.translate (fn c => str (Char.toUpper c)) s
|
||||
|
||||
(* convert_to_number : char -> string *)
|
||||
(* Covert a alphanumeric char into a numerical string *)
|
||||
fun convert_to_number (c : char) : string =
|
||||
if Char.isDigit c then str c else
|
||||
if Char.isUpper c then Int.toString (10 + ord c - ord #"A") else
|
||||
raise Domain
|
||||
|
||||
|
||||
(* verify_iban : string -> bool *)
|
||||
(* Check weather a string is a valid IBAN *)
|
||||
fun verify_iban str =
|
||||
let
|
||||
(* Remove spaces and make upper case *)
|
||||
val str = to_upper (removespace str)
|
||||
(* Fetch first two chars (country code) *)
|
||||
val country = String.substring (str, 0, 2)
|
||||
val len = country_code country
|
||||
in
|
||||
(* size test *)
|
||||
String.size str = len
|
||||
andalso
|
||||
(* Every char must be alphanumeric *)
|
||||
List.all Char.isAlphaNum (explode str)
|
||||
andalso
|
||||
let
|
||||
(* Reorder *)
|
||||
val str = String.substring (str, 4, String.size str - 4) ^ String.substring (str, 0, 4)
|
||||
(* Convert into digits *)
|
||||
val str = String.translate convert_to_number str
|
||||
(* Convert into a big number *)
|
||||
val number = valOf (IntInf.fromString str)
|
||||
in
|
||||
IntInf.mod (number, 97) = 1
|
||||
end
|
||||
end handle Subscript => false | Domain => false
|
||||
64
Task/IBAN/ZX-Spectrum-Basic/iban.zx
Normal file
64
Task/IBAN/ZX-Spectrum-Basic/iban.zx
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
10 REM REM Used the following as official standard:
|
||||
20 REM REM http://www.cnb.cz/cs/platebni_styk/iban/download/EBS204.pdf
|
||||
30 REM REM Pairs of ISO 3166 country code & expected IBAN length for this country
|
||||
40 LET c$="AL28 AD24 AT20 AZ28 BE16 BH22 BA20 BR29 BG22 CR21 HR21 CY28 CZ24 DK18 DO28 EE20 "
|
||||
50 LET c$=c$+"FO18 FI18 FR27 GE22 DE22 GI23 GR27 GL18 GT28 HU28 IS26 IE22 IL23 IT27 KZ20 KW30 "
|
||||
60 LET c$=c$+"LV21 LB28 LI21 LT20 LU20 MK19 MT31 MR27 MU30 MC27 MD24 ME22 NL18 NO15 PK24 PS29 "
|
||||
70 LET c$=c$+"PL28 PT25 RO24 SM27 SA24 RS22 SK24 SI19 ES24 SE24 CH21 TN24 TR26 AE23 GB22 VG24 "
|
||||
80 LET e$=""
|
||||
100 LET i$="GB82 WEST 1234 5698 7654 32": GO SUB 1000
|
||||
110 LET i$="gb82 west 1234 5698 7654 32": GO SUB 1000
|
||||
120 LET i$="GB82 TEST 1234 5698 7654 32": GO SUB 1000
|
||||
130 LET i$="GR16 0110 1250 0000 0001 2300 695": GO SUB 1000
|
||||
140 LET i$="IL62-0108-0000-0009-9999-999": GO SUB 1000
|
||||
900 STOP
|
||||
1000 REM IBAN check routine
|
||||
1010 LET explen=0: LET lenc=LEN c$
|
||||
1020 FOR i=1 TO lenc STEP 5
|
||||
1030 IF i$( TO 2)=c$(i TO i+1) THEN LET explen=VAL c$(i+2 TO i+3): GO TO 2000
|
||||
1040 NEXT i
|
||||
2000 LET match=explen>0
|
||||
2010 REM Continue if country code found
|
||||
2020 IF NOT match THEN LET e$="country code: "+i$( TO 2): GO TO 3000
|
||||
2030 REM Remove espace = convert to digital IBAN
|
||||
2040 LET d$=""
|
||||
2050 FOR i=1 TO LEN i$
|
||||
2060 IF i$(i)>" " THEN LET d$=d$+i$(i)
|
||||
2070 NEXT i
|
||||
2080 LET match=explen=LEN d$
|
||||
2090 REM Continue if length is correct
|
||||
2100 IF NOT match THEN LET e$="code length, expected length: "+STR$ explen: GO TO 3000
|
||||
2110 REM Create temporary string with country code appended
|
||||
2120 LET t$=d$(5 TO )+d$(1 TO 2)
|
||||
2130 REM Make big number, replacing letters by numbers using next conversion table: A=10 ... Z=35
|
||||
2140 LET b$=""
|
||||
2150 FOR i=1 TO LEN t$
|
||||
2160 LET c= CODE t$(i)
|
||||
2170 IF (c>64 AND c<91) THEN LET b$=b$+STR$ (c-55): GO TO 2200
|
||||
2190 IF (c>47 AND c<58) THEN LET b$=b$+t$(i)
|
||||
2200 NEXT i
|
||||
2210 REM MOD 97 on bignum$+"00" and subtract result from 98 to obtain control number
|
||||
2220 LET k$=b$+"00": GO SUB 4000
|
||||
2230 LET kk=98-mod97
|
||||
2240 REM Compare with control number in IBAN
|
||||
2250 LET match=VAL i$(3 TO 4)=kk
|
||||
2260 REM Continue if control number matches
|
||||
2270 IF NOT match THEN LET e$="check digits, should be: "+STR$ kk: GO TO 3000
|
||||
2280 REM Append kk to bignum$ and determine if MOD 97 results in 1
|
||||
2285 LET k$="0"+STR$ kk
|
||||
2290 LET k$=b$+k$(LEN k$-1 TO ): GO SUB 4000
|
||||
2300 LET match=mod97=1
|
||||
2310 REM Continue if mod 97
|
||||
2320 IF NOT match THEN LET e$="result from modulo 97"
|
||||
3000 IF match THEN PRINT " ": GO TO 3100
|
||||
3010 PRINT "in";: LET e$=" ***error!*** invalid "+e$
|
||||
3100 PRINT "valid IBAN: ";i$;e$: LET e$=""
|
||||
3110 RETURN
|
||||
4000 REM Modulo 97
|
||||
4010 LET mod97=0
|
||||
4020 FOR i=1 TO LEN k$
|
||||
4030 LET d$=STR$ (mod97)+k$(i)
|
||||
4040 LET mod97=FN m(VAL (d$),97)
|
||||
4050 NEXT i
|
||||
4060 RETURN
|
||||
5000 DEF FN m(a,b)=a-INT (a/b)*b: REM modulo
|
||||
6
Task/IBAN/Zkl/iban-1.zkl
Normal file
6
Task/IBAN/Zkl/iban-1.zkl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
var BN=Import("zklBigNum");
|
||||
fcn validateIBAN(iban){
|
||||
iban=iban-" \t";
|
||||
alphaNums.matches(iban) and (ibans.find(iban[0,2])==iban.len()) and
|
||||
( BN((iban[4,*]+iban[0,4]).apply("toInt",36)) % 97 == 1 )
|
||||
}
|
||||
12
Task/IBAN/Zkl/iban-2.zkl
Normal file
12
Task/IBAN/Zkl/iban-2.zkl
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
fcn validateIBAN(iban){
|
||||
iban=iban-" \t";
|
||||
alphaNums.matches(iban) and (ibans.find(iban[0,2])==iban.len()) and
|
||||
( (iban[4,*]+iban[0,4]).apply("toInt",36) : mod97(_) == 1 )
|
||||
}
|
||||
fcn mod97(str){
|
||||
n:=0; m:=9; M:=0; while(N:=str[n,m]){
|
||||
M=((M.toString()+N).toInt()) % 97;
|
||||
n+=m; m=7;
|
||||
}
|
||||
M
|
||||
}
|
||||
10
Task/IBAN/Zkl/iban-3.zkl
Normal file
10
Task/IBAN/Zkl/iban-3.zkl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
var alphaNums=RegExp("^[0-9A-Z]+$");
|
||||
var ibans= // Dictionary("AD":24, ...)
|
||||
("AD24 AE23 AL28 AO25 AT20 AZ28 BA20 BE16 BF27 BG22 BH22 BI16 "
|
||||
"BJ28 BR29 CG27 CH21 CI28 CM27 CR21 CV25 CY28 CZ24 DE22 DK18 "
|
||||
"DO28 DZ24 EE20 EG27 ES24 FI18 FO18 FR27 GA27 GB22 GE22 GI23 "
|
||||
"GL18 GR27 GT28 HR21 HU28 IE22 IL23 IR26 IS26 IT27 JO30 KW30 "
|
||||
"KZ20 LB28 LI21 LT20 LU20 LV21 MC27 MD24 ME22 MG27 MK19 ML28 "
|
||||
"MR27 MT31 MU30 MZ25 NL18 NO15 PK24 PL28 PS29 PT25 QA29 RO24 "
|
||||
"RS22 SA24 SE24 SI19 SK24 SM27 SN28 TN24 TR26 UA29 VG24")
|
||||
.split(" ").pump(D(),fcn(w){return(w[0,2],w[2,*].toInt())});
|
||||
20
Task/IBAN/Zkl/iban-4.zkl
Normal file
20
Task/IBAN/Zkl/iban-4.zkl
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// all valid
|
||||
T("GB82 WEST 1234 5698 7654 32","GB82WEST12345698765432",
|
||||
"GR16 0110 1250 0000 0001 2300 695","GB29 NWBK 6016 1331 9268 19",
|
||||
"SA03 8000 0000 6080 1016 7519","CH93 0076 2011 6238 5295 7",
|
||||
"IL62 0108 0000 0009 9999 999")
|
||||
.apply(validateIBAN).println();
|
||||
|
||||
// all invalid
|
||||
T("gb82 west 1234 5698 7654 32","GB82 TEST 1234 5698 7654 32",
|
||||
"GB82 WEST 1243 5698 7654 32","AE82 WEST 1234 5698 7654 32"
|
||||
"IL62-0108-0000-0009-9999-999","US12 3456 7890 0987 6543 210",
|
||||
"GR16 0110 1250 0000 0001 2300 695X","GT11 2222 3333 4444 5555 6666 7777",
|
||||
"MK11 2222 3333 4444 555")
|
||||
.apply(validateIBAN).println();
|
||||
|
||||
// white list from Scala
|
||||
("AD1200012030200359100100 AE260211000000230064016 AL47212110090000000235698741 "
|
||||
...
|
||||
"CH9300762011623852957").split()
|
||||
.apply(validateIBAN).toString(*).println();
|
||||
Loading…
Add table
Add a link
Reference in a new issue