Schreiben Sie einen IBAN-Validator

8

Schreiben Sie ein Programm (der Hauptteil der Funktion reicht aus), das eine Zeichenfolge alphanumerischer Zeichen akzeptiert und gemäß ISO 13616: 2007 validiert. Der Validierungsalgorithmus lautet (Quelle: Wikipedia-Artikel auf IBAN http://en.wikipedia.org/wiki/International_Bank_Account_Number ):

Validierung der IBAN Eine IBAN wird validiert, indem sie in eine Ganzzahl konvertiert und eine grundlegende Mod-97-Operation (wie in ISO 7064 beschrieben) ausgeführt wird. Wenn die IBAN gültig ist, ist der Rest gleich 1. Der Algorithmus der IBAN-Validierung lautet wie folgt:

  • Überprüfen Sie, ob die gesamte IBAN-Länge je nach Land korrekt ist. Wenn nicht, ist die IBAN ungültig. Die korrekten IBAN-Längen finden Sie hier: http://pastebin.com/kp4eECVk ( siehe auch unten), sortiert nach der Länge der IBAN-Nummer. Die ersten 2 Zeichen jeder Nummer sind die Landesvorwahl. Alle anderen Zeichen (Kleinbuchstaben auf dem Pastebin, können aber in der tatsächlichen IBAN beliebig sein) hinter den ersten 2 können beliebige alphanumerische Zeichen sein.
  • Verschieben Sie die vier Anfangszeichen an das Ende der Zeichenfolge.
  • Ersetzen Sie jeden Buchstaben in der Zeichenfolge durch zwei Ziffern, wodurch die Zeichenfolge erweitert wird, wobei A = 10, B = 11, ..., Z = 35.
  • Interpretieren Sie die Zeichenfolge als Dezimalzahl und berechnen Sie den Rest dieser Zahl bei Division durch 97

Wenn der Rest 1 ist, ist der Prüfziffertest bestanden und die IBAN ist möglicherweise gültig.

Beispiel (fiktive Bank in Großbritannien, Bankleitzahl 12-34-56, Kontonummer 98765432):

- IBAN:               GB82 WEST 1234 5698 7654 32 
- Rearrange:          W E S T12345698765432 G B82
- Convert to integer: 3214282912345698765432161182    
- Compute remainder:  3214282912345698765432161182    mod 97 = 1

Der Algorithmus kann true (oder einen wahrheitsgemäßen Wert) zurückgeben, wenn die Zahl gültig ist, und false (oder einen falschen Wert), wenn die Zahl gemäß dem Algorithmus ungültig ist. Sie müssen nicht überprüfen, ob die Nummer tatsächlich vorhanden ist, sondern nur, wenn sie gültig ist. Der Algorithmus muss für jede der verschiedenen genehmigten IBAN-Nummern funktionieren, die im obigen Wikipedia-Artikel erwähnt werden. Der Algorithmus sollte mit Zahlen mit oder ohne Trennzeichen zwischen zwei alphanumerischen Zeichen kompatibel sein. Das Trennzeichen kann entweder Punkte, Leerzeichen oder Bindestriche sein, und eine Zahl kann verschiedene Arten von Trennzeichen enthalten.

Es gelten die üblichen Lücken: keine externen Ressourcen, keine integrierten Funktionen oder Methoden.

Der Puzzletyp ist Code Golf. Der kürzeste Code in Bytecount gewinnt. Das zur Ausführung des Programms erforderliche Standard-Boilerplate (z. B. Namespace, Klasse, Funktionsdeklaration in OOP) ist nicht in der Anzahl der Bytes enthalten.

Bonus: Wenn Sie die korrekt formatierte IBAN-Nummer (gemäß dem nationalen Format auf Wikipedia) anstelle von true im Fall einer gültigen Nummer zurückgeben können, erhalten Sie eine 25% ige Reduzierung Ihrer Punktzahl. Wenn die Zahl ungültig ist, geben Sie eine Literalzeichenfolge mit dem Wert "Ungültig" zurück.


Kopie der IBAN-Längen für den Fall, dass der Pastebin jemals entfernt wird:

Country;Chars;IBAN Fields
Norway;15;NOkk bbbb cccc ccx
Belgium;16;BEkk bbbc cccc ccxx
Burundi;16;BIkk nnnn nnnn nnnn
Denmark;18;DKkk bbbb cccc cccc cc
Faroe Islands;18;FOkk bbbb cccc cccc cx
Finland;18;FIkk bbbb bbcc cccc cx
Greenland;18;GLkk bbbb cccc cccc cc
Netherlands;18;NLkk bbbb cccc cccc cc
Macedonia;19;MKkk bbbc cccc cccc cxx
Slovenia;19;SIkk bbss sccc cccc cxx
Austria;20;ATkk bbbb bccc cccc cccc
Bosnia and Herzegovina;20;BAkk bbbs sscc cccc ccxx
Estonia;20;EEkk bbss cccc cccc cccx
Kazakhstan;20;KZkk bbbc cccc cccc cccc
Lithuania;20;LTkk bbbb bccc cccc cccc
Luxembourg;20;LUkk bbbc cccc cccc cccc
Costa Rica;21;CRkk bbbc cccc cccc cccc c
Croatia;21;HRkk bbbb bbbc cccc cccc c
Latvia;21;LVkk bbbb cccc cccc cccc c
Liechtenstein;21;LIkk bbbb bccc cccc cccc c
Switzerland;21;CHkk bbbb bccc cccc cccc c
Bahrain;22;BHkk bbbb cccc cccc cccc cc
Bulgaria;22;BGkk bbbb ssss ddcc cccc cc
Georgia;22;GEkk bbcc cccc cccc cccc cc
Germany;22;DEkk bbbb bbbb cccc cccc cc
Ireland;22;IEkk aaaa bbbb bbcc cccc cc
Montenegro;22;MEkk bbbc cccc cccc cccc xx
Serbia;22;RSkk bbbc cccc cccc cccc xx
United Kingdom;22;GBkk bbbb ssss sscc cccc cc
Gibraltar;23;GIkk bbbb cccc cccc cccc ccc
Israel;23;ILkk bbbn nncc cccc cccc ccc
United Arab Emirates;23;AEkk bbbc cccc cccc cccc ccc
Andorra;24;ADkk bbbb ssss cccc cccc cccc
Czech Republic;24;CZkk bbbb ssss sscc cccc cccc
Moldova;24;MDkk bbcc cccc cccc cccc cccc
Pakistan;24;PKkk bbbb cccc cccc cccc cccc
Romania;24;ROkk bbbb cccc cccc cccc cccc
Saudi Arabia;24;SAkk bbcc cccc cccc cccc cccc
Slovakia;24;SKkk bbbb ssss sscc cccc cccc
Spain;24;ESkk bbbb gggg xxcc cccc cccc
Sweden;24;SEkk bbbc cccc cccc cccc cccx
Tunisia;24;TNkk bbss sccc cccc cccc cccc
Virgin Islands;24;VGkk bbbb cccc cccc cccc cccc
Algeria;24;DZkk nnnn nnnn nnnn nnnn nnnn
Portugal;25;PTkk bbbb ssss cccc cccc cccx x
Angola;25;AOkk nnnn nnnn nnnn nnnn nnnn n
Cape Verde;25;CVkk nnnn nnnn nnnn nnnn nnnn n
Mozambique;25;MZkk nnnn nnnn nnnn nnnn nnnn n
Iceland;26;ISkk bbbb sscc cccc iiii iiii ii
Turkey;26;TRkk bbbb bxcc cccc cccc cccc cc
Iran;26;IRkk nnnn nnnn nnnn nnnn nnnn nn
France;27;FRkk bbbb bggg ggcc cccc cccc cxx
Greece;27;GRkk bbbs sssc cccc cccc cccc ccc
Italy;27;ITkk xaaa aabb bbbc cccc cccc ccc
Mauritania;27;MRkk bbbb bsss sscc cccc cccc cxx
Monaco;27;MCkk bbbb bsss sscc cccc cccc cxx
San Marino;27;SMkk xaaa aabb bbbc cccc cccc ccc
Burkina Faso;27;BFkk nnnn nnnn nnnn nnnn nnnn nnn
Cameroon;27;CMkk nnnn nnnn nnnn nnnn nnnn nnn
Madagascar;27;MGkk nnnn nnnn nnnn nnnn nnnn nnn
Albania;28;ALkk bbbs sssx cccc cccc cccc cccc
Azerbaijan;28;AZkk bbbb cccc cccc cccc cccc cccc
Cyprus;28;CYkk bbbs ssss cccc cccc cccc cccc
Dominican Republic;28;DOkk bbbb cccc cccc cccc cccc cccc
Guatemala;28;GTkk bbbb cccc cccc cccc cccc cccc
Hungary;28;HUkk bbbs sssk cccc cccc cccc cccx
Lebanon;28;LBkk bbbb cccc cccc cccc cccc cccc
Poland;28;PLkk bbbs sssx cccc cccc cccc cccc
Benin;28;BJkk annn nnnn nnnn nnnn nnnn nnnn
Ivory Coast;28;CIkk annn nnnn nnnn nnnn nnnn nnnn
Mali;28;MLkk annn nnnn nnnn nnnn nnnn nnnn
Senegal;28;SNkk annn nnnn nnnn nnnn nnnn nnnn
Brazil;29;BRkk bbbb bbbb ssss sccc cccc ccct n
Palestinian;29;PSkk bbbb xxxx xxxx xccc cccc cccc c
Qatar;29;QAkk bbbb cccc cccc cccc cccc cccc c
Ukraine;29;UAkk bbbb bbcc cccc cccc cccc cccc c
Jordan;30;JOkk bbbb nnnn cccc cccc cccc cccc cc
Kuwait;30;KWkk bbbb cccc cccc cccc cccc cccc cc
Mauritius;30;MUkk bbbb bbss cccc cccc cccc cccc cc
Malta;31;MTkk bbbb ssss sccc cccc cccc cccc ccc
Nzall
quelle
3
Für alle, die vorgeschlagen haben, Perl- und Python-Tags hinzuzufügen: Sprach-Tags in Herausforderungen sollten verwendet werden, um die Herausforderung auf eine bestimmte Sprache zu beschränken (oder zumindest denke ich, dass dies die Absicht von ihnen ist). Diese Herausforderung steht allen Sprachen offen. Daher habe ich die Bearbeitung abgelehnt.
Nzall

Antworten:

4

J (294 - 73,5 = 220,5)

Ich habe die Funktionsdefinition ( f=:3 :0... )) nicht gezählt, da sie als Boilerplate betrachtet werden kann. Das Zählen des gesamten Blocks ergibt eine Punktzahl von 304 - 76 = 228 .

f=:3 :0
>((1=97|1".'x',~' '-.~":48-~k-7*64<k=.3&u:4|.b)*(#b)=15+1 i.~+/"1(2{.b)&E.;.2'NO.BEBI..DKFOFIGLNL.MKSI.ATBAEEKZLTLU.CRHRLVLICH.BHBGGEDEIEMERSGB.GIILAE.ADCZMDPKROSASKESSETNVGDZ.PTAOCVMZ.ISTRIR.FRGRITMRMCSMBFCMMG.ALAZCYDOGTHULBPLBJCIMLSN.BRPSQAUA.JOKWMU.MT.'){'Invalid';1}.;' '&,&.>_4<\b=.y-.' -.'
)

Tests:

   NB. invalid numbers
   f ''
Invalid
   f 'GB82 WEST 1234 5698 7654 31'
Invalid
   f 'NL82 WEST 1234 5698 7654 32'
Invalid

   NB. different separators and formatting
   f 'GB82.WEST.1234.5698.7654.32'
GB82 WEST 1234 5698 7654 32
   f 'GB82-WEST-1234-5698-7654-32'
GB82 WEST 1234 5698 7654 32
   f 'GB82WEST12345698765432'
GB82 WEST 1234 5698 7654 32
   f 'GB82 WEST 1234 5698 7654 32'
GB82 WEST 1234 5698 7654 32
   f 'GB.82-WE ST-12.345698.76-5432'
GB82 WEST 1234 5698 7654 32

   NB. wikipedia examples
   f 'GR16 0110 1250 0000 0001 2300 695'
GR16 0110 1250 0000 0001 2300 695
   f 'CH93 0076 2011 6238 5295 7'
CH93 0076 2011 6238 5295 7
   f 'SA03 8000 0000 6080 1016 7519'
SA03 8000 0000 6080 1016 7519
   f 'GB29 NWBK 6016 1331 9268 19'
GB29 NWBK 6016 1331 9268 19

Erläuterung:

  • b=.y-.' -.': Entfernen Sie alle Trennzeichen aus dem Argument und speichern Sie das Ergebnis in b.
  • 1}.;' '&,&.>_4<\b: bIn Vierergruppen aufteilen, vor jeder Gruppe ein Leerzeichen einfügen, den Gruppen beitreten und das führende Leerzeichen entfernen. Wenn yeine gültige IBAN-Nummer enthalten ist, ist dies ihre kanonische Darstellung (dh Vierergruppen, durch Leerzeichen getrennt, wobei die letzte Gruppe möglicherweise weniger als vier Elemente enthält).
  • (... ){'Invalid';: Erstellen Sie ein Array mit der Zeichenfolge Invalidals Element 0 und der formatierten IBAN-Nummer als Element 1. Wählen Sie die richtige aus, je nachdem, ob die IBAN-Nummer gültig ist:

    • Überprüfen Sie die Länge:
      • 'NO.BEBI.---.JOKWU.MT.': Eine Liste aller Ländercodes für jede Länge, getrennt durch Punkte
      • +/"1(2{.b)&E.;.2: Gruppieren Sie die Zeichenfolge nach den Punkten und sehen Sie, welche den angegebenen Ländercode enthält (die ersten beiden Elemente von b).
      • 15+1 i.~: Finden Sie den Index des passenden und fügen Sie ihn hinzu 15, um die Länge zu ermitteln.
      • (#b)=: Überprüfen Sie es mit der tatsächlichen Länge von b.
    • Überprüfen Sie die Nummer:
      • 4|.b: um b4 nach links drehen (neu anordnen)
      • k=.3&u:: Finden Sie den ASCII-Wert für jede Nummer
      • 48-~k-7*64<k: subtrahieren Sie 7 von jedem Buchstaben, dann subtrahieren Sie 48 von allen und geben Sie die Werte an
      • 1".'x',~' '-.~":: formatieren, Leerzeichen entfernen, am Ende ein 'x' hinzufügen (für den hochpräzisen Modus, der für große Zahlen erforderlich ist) und wieder in eine Zahl umwandeln
      • 1=97|: überprüfe ob die Zahl mod 97 gleich 1 ist.
  • >: Entpacken Sie die resultierende Zeichenfolge
Marinus
quelle
4

CJam, 151,5 141,75 Punkte

0000000: 6c22 202e 2d22 2d3a 512c 220f a86e 5136  l" .-"-:Q,"..nQ6
0000010: 1bff 75f6 e8e4 0b35 5dab f190 0d85 59c4  ..u....5].....Y.
0000020: 1938 4366 3d29 5eaa e879 024a 77d9 8baf  .8Cf=)^..y.Jw...
0000030: 5c16 3258 a4d2 4e6c 1a60 429f affa b8f4  \.2X..Nl.`B.....
0000040: 435d e706 457b 89a9 16b8 1d4b 08f7 9970  C]..E{.....K...p
0000050: eeb9 7467 f8e9 c935 33be 2467 3dd4 1afb  ..tg...53.$g=...
0000060: e2ec 20cc 99e4 2783 cb96 512d f9f8 7e75  .. ...'...Q-..~u
0000070: 7066 4307 2232 3536 6232 3762 2740 662b  pfC."256b27b'@f+
0000080: 2740 2f7b 5132 3c23 3126 217d 235f 573e  '@/{Q2<#1&!}#_W>
0000090: 462a 2b3d 5134 6d3c 412c 7327 5b2c 3635  F*+=Q4m<A,s'[,65
00000a0: 3e2b 6623 737e 3937 2531 3d5d 312d 2249  >+f#s~97%1=]1-"I
00000b0: 6e76 616c 6964 2251 342f 532a 3f         nvalid"Q4/S*?

Das obige Programm ist 189 Bytes lang und qualifiziert sich für den Bonus.

Auf Kosten von 26 weiteren Bytes - bei einer Gesamtpunktzahl von 161,25 - können wir nicht druckbare Zeichen vermeiden:

l" .-"-:Q,",YER,moTd$V6nH\-Mh/I-z(]k!uw()=j9_[C3n&As0(F;TAn$eB-r%:p+^b,1Y.j;thavi@!d,Dt7M_x-5V:#o/m_CKj-c*Imy~IjXPBCo?aM#lrN:[email protected]"33f-94b27b'@f+'@/{Q2<#1&!}#_W>F*+=Q4m<A,s'[,65>+f#s~97%1=]1-"Invalid"Q4/S*?

Sie können diese Version im CJam-Interpreter testen .

Beispiellauf

$ cat gen.cjam
"l\" .-\"-:Q,"[32,15>{[
"NO"15"BE"16"BI"16"DK"18"FO"18"FI"18"GL"18"NL"18"MK"19"SI"19
"AT"20"BA"20"EE"20"KZ"20"LT"20"LU"20"CR"21"HR"21"LV"21"LI"21
"CH"21"BH"22"BG"22"GE"22"DE"22"IE"22"ME"22"RS"22"GB"22"GI"23
"IL"23"AE"23"AD"24"CZ"24"MD"24"PK"24"RO"24"SA"24"SK"24"ES"24
"SE"24"TN"24"VG"24"DZ"24"PT"25"AO"25"CV"25"MZ"25"IS"26"TR"26
"IR"26"FR"27"GR"27"IT"27"MR"27"MC"27"SM"27"BF"27"CM"27"MG"27
"AL"28"AZ"28"CY"28"DO"28"GT"28"HU"28"LB"28"PL"28"BJ"28"CI"28
"ML"28"SN"28"BR"29"PS"29"QA"29"UA"29"JO"30"KW"30"MU"30"MT"31
]2/{1=L=},0f=_!!{:+}*}fL]"@"*'@f-27b256b:c`"\\\\"/"\\"*
"256b27b'@f+'@/{Q2<#1&!}#_W>F*+=Q4m<A,s'[,65>+f#s~97%1=]1-\"Invalid\"Q4/S*?"
$ LANG=en_US cjam gen.cjam | tee >(cksum) > iban.cjam
770150303 189
$ LANG=en_US cjam iban.cjam <<< GB82WEST12345698765432; echo
GB82 WEST 1234 5698 7654 32

Wie es funktioniert

"…"256b27b'@f+"

konvertiert die Zeichenfolge "…"in eine Ganzzahl, indem sie als Basis-256-Zahl betrachtet wird, und dann in ein Array von Ganzzahlen, indem sie als Basis-27-Zahl betrachtet wird, fügt den Zeichencode @jeder Ziffer hinzu und wandelt sie dabei in Zeichen um.

Infolgedessen wird der folgende Code ausgeführt:

" Read one line from STDIN, remove allowed separators, store the result in variable
  “Q” and push its length (“,”).                                                      ";

l" .-"-:Q,

" Push the string from above.
  The correct number of characters for country code “NO” is 15.
  The correct number of characters for country codes “BE” and “BI” is 16.
  The number of characters should never be 17.
  ⋮                                                                                  ";

"NO@BEBI@@DKFOFIGLNL@MKSI@ATBAEEKZLTLU@CRHRLVLICH@BHBGGEDEIEMERSGB@"
"GIILAE@ADCZMDPKROSASKESSETNVGDZ@PTAOCVMZ@ISTRIR@FRGRITMRMCSMBFCMMG@"
"ALAZCYDOGTHULBPLBJCIMLSN@BRPSQAUA@JOKWMU@MT"++

" Split the above string at the at signs (“@”).                                       ";

'@/

" Find the index of the (first) substring such that the index of the country code 
  (“Q2<”) in the substring is even.                                                   ";

{Q2<#1&!}#

" If the country code is invalid, the index will be -1. If the index is greater than 
  -1 (“W>”), add 15 to it; if it isn't, leave -1 on the stack.                        ";

_W>F*+

" Compare the result to the length of the IBAN. Push 1 if they match and 0 otherwise. ";

=

" Push the IBAN rotated to the left by four characters.                               ";

Q4m<

" “A,s'[,65>+” pushes “0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ”. For each character of 
   the IBAN, push its index in that string (-1 if not present).                       ";

A,s'[,65>+f#

" Stringify (“s”) the result, interpret the string (“~”) and compute the residue of
  the (topmost) resulting integer modulo 97.                                          ";

s97%

" Push 1 if the residue is 1; otherwise, push 0                                       ";

1=

" Wrap the entire stack in an array and remove the integer 1 from it. If the IBAN is
  valid, the array will be empty.

" If the result is falsy, the IBAN is valid; split it into substrings of length 4
  and join them using spaces (“S”). Otherwise, the IBAN is invalid; say so.           ";

"Invalid"Q4/S*?
Dennis
quelle
LANG=en_US java -jar cjam-0.6.2.jar iban.cjam<<<GB82WEST12345698765432Ausgaben Ungültig, was mache ich falsch (unter Windows 8.1 und Cygwin)?
@professorfish: Ich habe keinen Windows-Computer, daher kann ich dies nicht überprüfen. Beginnen wir jedoch mit der Überprüfung der folgenden Punkte: 1. Wurde iban.cjam erfolgreich generiert? md5sum iban.cjamsollte drucken 1960c33e31ae5646cd0400826757b3bc. 2. Ist das Gebietsschema ordnungsgemäß installiert? Sie können dies durch Ausführen überprüfen locale -a | grep en_US.
Dennis
Es wurde nicht richtig generiert ( fb620d509887f1a7298c3e5ff312401a). locale -a|grep en_USAusgänge en_USunden_US.utf8
@professorfish: Interessant. Sie können dies versuchen, um die Datei iban.cjam zu vermeiden : LANG=en_US cjam <(LANG=en_US cjam gen.cjam) <<< GB82WEST12345698765432. Ich habe meiner Antwort eine Nur-ASCII-Version hinzugefügt, die leichter zu überprüfen sein sollte.
Dennis
2

Bash, 738 519 444 434 427

Hier ist etwas, um uns anzufangen, ich habe es geschrieben (und 317 Zeichen gespeichert, hauptsächlich im Speichercode-Bit des Ländercodes), während sich die Frage in der Sandbox befand. Lassen Sie mich wissen, wenn es irgendwelche Probleme gibt.

Die Funktion liest aus stdin, was in Bash durchaus üblich ist (die Frage lautet "Akzeptiert eine Zeichenfolge alphanumerischer Zeichen", dies muss nicht über Argumente erfolgen).

Es gibt 0 zurück, wenn die IBAN gültig ist, und einen Wert ungleich Null, wenn sie ungültig ist.

Eine IBAN, die andere Zeichen als die Trennzeichen enthält . -und A-Z0-9ungültig ist

t=return
v=`tr -d .\ -`
[ "`tr -dc A-Z0-9<<<$v`" = $v ]||$t
((${#v}>9))||$t
r=`grep -oE "[0-9]+[A-Z]{2}*${v:0:2}"<<<15NO16BEBI18DKFIFOGLNL19MKSI20ATBAEEKZLTLU21CHCRHRLILV22BGBHDEGBGEIEMERS23AEGIIL24ADCZDZESMDPKROSASESKTNVG25AOCVMZPT26IRISTR27BFCMFRGRITMCMGMRSM28BJCICYDOGTHULBMLPLSNAZ29BRPSQAUA30JOKWMU31MT`
[ "${r:0:2}" = ${#v} ]||$t
v=${v:4:99}${v:0:4}
d=({A..Z})
for a in {10..35};{
v=${v//${d[a-10]}/$a}
}
$t `bc<<<$v%97-1`

Erläuterung

t=return # Alias return to $t
v=`tr -d .\ -` # Remove delimiters from STDIN and save to a variable $v.
# If you want the function to take the IBAN as an argument, insert <<<$1 just before the last ` in the line above
# Check that the number now contains no characters other than A-Z0-9 (i.e. if all other characters are removed, the string should remain the same because there aren't any of them)
# If not, return. By default, return uses the exit status of the previous command, which will be 1
[ "`tr -dc A-Z0-9<<<$v`" = $v ]||$t
# Check that $v is long enough to have a country code at the start, return if not
# I could have put 2 instead of 9, but the character count is the same
((${#v}>9))||$t
# give grep the country code data string, which is of the format <length1><country><country><length2><country><country><country>...
# for example, this tells you that EE has an IBAN length of 20
# grep searches for a number ([0-9]+), followed by any number including zero of country codes ([A-Z]{2}*), followed by the first two characters of the input IBAN, i.e. its country code (${v:0:2})
# -o makes grep only output the match, not the line containing it; -E enables extended regexes
# The result is saved to the variable $r
r=`grep -oE "[0-9]+[A-Z]{2}*${v:0:2}"<<<15NO16BEBI18DKFIFOGLNL19MKSI20ATBAEEKZLTLU21CHCRHRLILV22BGBHDEGBGEIEMERS23AEGIIL24ADCZDZESMDPKROSASESKTNVG25AOCVMZPT26IRISTR27BFCMFRGRITMCMGMRSM28BJCICYDOGTHULBMLPLSNAZ29BRPSQAUA30JOKWMU31MT`
# Check that the length specified by the country code, the first two chars of $r, is equal to the actual IBAN's length ${#v}. return 1 if not.
[ "${r:0:2}" = ${#v} ]||$t
v=${v:4:99}${v:0:4} # Put the first 4 chars to the back
d=({A..Z}) # Make an array of letters A to Z
# Loop for each number from 10 to 35
for a in {10..35};{
# in the IBAN, replace letters A to Z by the corresponding number from 10 to 35
v=${v//${d[a-10]}/$a}
}
# $v is now an integer
# note: I used bc here because Bash's built-in arithmetic couldn't handle big numbers
# find the remainder of dividing $v by 97, subtract 1, and return the value
# if the remainder is 1, then the IBAN is valid and 1-1=0 is returned.
$t `bc<<<$v%97-1`

Beispiele

ibanfn<<<'-GB82-WEST-1234 5698.7654.32    ' #returns 0, valid
ibanfn<<<'-GB82-WEST-1234 5698.7654.33    ' #returns 27, invalid, fails remainder test
ibanfn<<<'GB82 WEST 1234 5698 7654 32a'     #returns 1, invalid, contains invalid character a
ibanfn<<<'YY82 WEST 1234 5698 7654 32'      #returns 1, invalid, country code does not exist
ibanfn<<<'GB82 WEST 1234 5698 7654 3210'    #returns 1, invalid, wrong length

quelle
2

Python 3 - (483 - 25%) 362

import re
def c(i):
 i=re.sub('\W','',i);q,s='NOBEBIDKFOFIGLNLMKSIATBAEEKZLTLUCRHRLVLICHBHBGGEDEIEMERSGBGIILAEADCZMDPKROSASKESSETNVGDZPTAOCVMZISTRIRFRGRITMRMCSMBFCMMGALAZCYDOGTHULBPLBJCIMLSNBRPSQAUAJOKWMUMT',i
 for m in b" !!#####$$%%%%%%&&&&&''''''''((())))))))))))****+++,,,,,,,,,------------....///0":
  if(i[:2],len(i)+17)==(q[:2],m):
   i=i[4:]+i[:4]
   for z in range(26):i=re.sub(chr(65+z),str(z+10),i)
   return(int(i)%97==1)and re.findall('.{,4}',s)or 0
  q=q[2:]
 return 0
LemonBoy
quelle
WT ?? - das ist etwas Golf! Gute Arbeit. Aus der Ferne sieht es ein bisschen wie Linienrauschen aus ... j / k außerdem ist es eine Ergänzung ;-)
G. Cito
2

Perl (356 + 2 * 75% = 268,5)

Der Code ist so verwirrend, dass sogar die Syntaxhervorhebung von SE darin verloren geht :)

#!perl -ln
use bignum;s/\W//g;$_=$T=uc;$q=15;/\w/?$H{$_}=$q:$q++for'NO,BEBI,,NLGLDKFOFI,SIMK,KZEEATLTLUBA,HRCHLVCRLI,RSIEGEDEBGBHGBME,GIAEIL,SASESKESCZMDTNPKADDZVGRO,PTMZCVAO,TRISIR,CMMGMRSMITFRGRBFMC,ALAZPLCIGTHUSNCYDOBJLBML,UABRQAPS,KWMUJO,MT'=~/,|../g;/../;$q=$H{$&}==y///c;/..../;$_=$'.$&;s/[A-Z]/ord($&)-55/ge;print+(Invalid,join' ',($T=~/.{1,4}/g))[1==$_%97*$q]

Erläuterung

#!perl -nl

-nbedeutet, stdin Zeile für Zeile zu lesen; -lFügt neue Zeilen zum Drucken hinzu

use bignum;

Erforderlich für den Modulo-Betrieb später, um den korrekten Wert zurückzugeben.

s/\W//g;

Entfernen Sie alles, was nicht \ w ist, aus IBAN.

$_=$T=uc;

Konvertieren Sie die iban-Nummer in Großbuchstaben und speichern Sie sie in $ T. - wird später zum hübschen Drucken verwendet.

$q=15;

Setzen Sie die temporäre Variable auf 15. Sie wird verwendet, um eine Hash-Tabelle mit Ländercode für die Zuordnung der Iban-Länge zu erstellen.

/\w/ ? $H{$_}=$q : $q++
for 'NO,BEBI,,NLGLDKFOFI,SIMK,KZEEATLTLUBA,HRCHLVCRLI,RSIEGEDEBGBHGBME,GIAEIL,SASESKESCZMDTNPKADDZVGRO,PTMZCVAO,TRISIR,CMMGMRSMITFRGRBFMC,ALAZPLCIGTHUSNCYDOBJLBML,UABRQAPS,KWMUJO,MT' =~ /,|../g;

Teilen Sie die große Zeichenfolge in ein Array von Kommas oder aus zwei Buchstaben bestehenden Ländercodes auf und wiederholen Sie den Vorgang. Wenn das Element mit einem Buchstaben beginnt, handelt es sich um einen Ländercode. Speichern Sie ihn im Hash mit einem Wert von $ q. Andernfalls bedeutet ein Komma, $ q zu erhöhen. NO erhält also den Wert 15, BE und BI den Wert 16 und so weiter.

/../;

stimmen mit den ersten beiden Zeichen von IBAN überein (der Ländercode)

$q=$H{$&}==y///c;

Überprüfen Sie, ob IBAN die richtige Länge für den Ländercode hat. Speichern Sie das Ergebnis in $ q

/..../;$_=$'.$&; 

Verschieben Sie die ersten vier Zeichen an das Ende von IBAN

s/[A-Z]/ord($&)-55/ge;

Ersetzen Sie alle Buchstaben durch entsprechende Zahlen, beginnend mit A = 10

print+(Invalid,join' ',($T=~/.{1,4}/g))[1==$_%97*$q]

Drucken Sie entweder "Ungültig" oder die hübsch gedruckte IBAN. 1==$_%97*$qwird nur 1für eine IBAN mit einer korrekten Länge und einem korrekten Rest gleich sein.

chinesisches perl goth
quelle
1
nett! Im " perleinzigen" Subwettbewerb gewinnen Sie ;-) Auch wenn es verwirrend ist, können Sie versuchen , es ein wenig wie im Bash-Beispiel zu erklären? Bitte schön?! Wenn du deine erklärst, erkläre ich meine :-) (obwohl ich vielleicht zuerst einen deiner Tricks aus dem IBAN-Längenland stehlen würde). Prost.
G. Cito
2

Perl 6 - 354 Zeichen - (Bonus nicht sicher)

my $r = slurp 'ir';
my @cs = $r.comb(/(\D)+/);my @ns = $r.comb(/(\d)+/);
my %h;
for @ns Z @cs -> $n, $c {%h{$n}=[$c.comb(/\w**2/)]};
for my @ =lines() {
 my $o=$_;
 my $y=$_.substr(0,2);
 $_=s:g/\s|\-|\.//.uc.comb.rotate(4).join;
 my $l=$_.chars ; 
 $_.=trans(['A'..'Z'] => ['10'..'35']);
 next if $y !~~ %h{$l}.any;
 say $_%97==1??"$o ok"!!"Invalid";
}

Lesen von Eingaben von IBANS.txton STDINund Schlürfen der Regeln aus der Datei ir(ich habe die Regeln aus der Summe herausgelassen, falls sie Boilerplate waren - die Regeldatei besteht aus 191 Zeichen, sodass die Summe 545 wäre.

 perl6 ibanvalidate.p6 IBANS.txt

IBANS.txt ist wie folgt:

GB82 WEST 1234 5698 7654 32
GB82-WEST-1234-5698-7654-32
gb82-west-1234-5698-7654-32
GB82WEST12345698765432
GB82.WEST.1234.5698.7654.32
GR16 0110 1250 0000 0001 2300 695
GB82 WEST 1234 5698 7654 31
NL82 WEST 1234 5698 7654 32
GB29 NWBK 6016 1331 9268 19
Whee perl6
CANADA 000 Banks 007 911

Anmerkungen

  • validiert Ländercode und Länge und gibt wie folgt aus
  • Anzahl der Zeichen ab: wc -m ibanvalidate.p6
  • Derzeit wird nicht viel Fehler bei der Überprüfung der Eingabe überprüft.
  • Leerzeichen sind in Perl6 von Bedeutung (oder wichtiger als Perl 5) und werden daher gezählt.

Typische Ausgabe:

GB82 WEST 1234 5698 7654 32 ok
GB82-WEST-1234-5698-7654-32 ok
GB82WEST12345698765432 ok
GB82.WEST.1234.5698.7654.32 ok
GR16 0110 1250 0000 0001 2300 695 ok
Invalid
GB29 NWBK 6016 1331 9268 19 ok

Dies ist kein typischer Perl6-Code (insbesondere die combZeilen, die ein freundlicher und einflussreicher Perl-Entwickler im Vorbeigehen erwähnt hat): Ich bin ein Anfänger. Sobald der Wettbewerb beendet ist, werde ich alle von Perl6-er vorgeschlagenen Änderungen hinzufügen / ändern und vornehmen. Danke fürs Spielen und nett sein :-)

G. Cito
quelle
Wo wird der Ländercode überprüft?
@professorfish ... Ich habe das in der falschen Version von Perl gemacht ;-) es werden mehr als 200 Zeichen hinzugefügt, da bin ich mir sicher.
G. Cito
1

Perl 6 , 311 Bytes, Punktzahl 233,25

{/:i^(..)<[A..Z0..9]>+$/&&'NobeBIdkfofiglNlmkSiatbaeekzltLucrhrlvliChbhbggedeiemersGbgiilAeadczmdpkrosaskessetnvgDzptaocvMzistrIrfrgritmrmcsmbfcmMgalazcydogthulbplbjcimlSnbrpsqaUajokwMumt'~~/^:i(..)*$($0)/&&.comb==$0.comb(/<:Lu>/)+15&&[.comb].rotate(4)>>.&{:36($_)}.join%97==1&&~.comb(4)||'Invalid'}o{TR/\ .-//}

Probieren Sie es online aus!

ich bin mir nicht sicher

  • wo Trennzeichen genau erlaubt sind. Ich entferne einfach alle.
  • ob die endgültig formatierte Ausgabe in Großbuchstaben erfolgen soll.

Erläuterung

{
  /                # Match against regex
    :i             #   ignore case
    ^              #   start of string
    (..)           #   country code (stored in $0)
    <[A..Z0..9]>+  #   alphanumeric characters
    $              #   end of string
  /
  &&
  'NobeBIdk...'    # Country code string with uppercase letter
                   # for each length increase
  ~~               # match against
  /                # regex
    :i             #   ignore case
    ^              #   start of string
    (..)*          #   series of two characters (stored in $0)
    $($0)          #   country code
  /
  &&
  .comb==          # IBAN length equals
  $0.comb(/<:Lu>/) # number of uppercase characters
  +15              # plus 15
  &&
  [.comb]          # Split IBAN into characters
  .rotate(4)       # Rotate by four
  >>.&{:36($_)}    # Convert each from base-36
  .join            # Join
  %97==1           # Modulo 97 check
  &&
  ~.comb(4)        # Add space after every four characters
  ||
  'Invalid'        # Return 'Invalid' if any of the checks failed
}
o                  # Function composition
{
  TR/\ .-//        # Remove space, dot, dash
}
nwellnhof
quelle
0

Python3.x (539 Zeichen - 25% = 404,25)

(Um zuerst gesagt zu werden: Ich bin ein bisschen verwirrt, was nach Ihren Regeln zu zählen ist, also habe ich nur meine gesamte Funktion gezählt.)

539 Zeichen - Einschließlich importund def IBAN(i):(Tabulatoren am Anfang der Zeile werden in Python trotzdem gezählt, sodass sie keine Rolle spielen)

Der Bonus wird wie in den Regeln angegeben angewendet.

def IBAN(i):
    import re
    i=re.sub(r'[^\w]','',i).upper()
    k=len(i)
    z=i[:2]in re.search(r'%s([A-Z ]*)'%k,'15NO16BE BI18DK FO FI GL NL19MK SI20AT BA ES KZ LT LU21CR HR LV LI CH22BH BG GE DE IE MK RS GB23GI IL AE24MD PK RO SA SK ES SE TN VG DZ25CV MZ26IS TR IR FR GR IT MR MC SM BF CM MG28AL AZ CY DO GT HU LB PL BJ CI ML SN29BR PS QA UA30JO KW MU31MT').group(1)or None
    if int(''.join([c if c.isdigit()else str(ord(c)-55)for c in i[4:]+i[:4]]))%97!=1 or z is None:return('Invalid')
    return(' '.join([i[0+j:4+j]for j in range(0,k,4)]))

Code mit Kommentaren (noch nicht abgeschlossen ... Ich bin viel zu müde, um den restlichen Teil der Kommentare zu schreiben ... das mache ich morgen)

def IBAN(i):
    import re
    # Remove all non word characters (including space) and change to uppercase
    # as0098-7*46.76A -> AS009874676A
    i=re.sub(r'[^\w]','',i).upper()
    # Get the length of it because I need it later multiple times
    k=len(i)
    #                   r'%s([A-Z ]*)'%k = Replace %s with the length of i
    #         re.search(                ,'15NO16BE BI18DK FO FI GL NL19MK SI20AT BA ES KZ LT LU21CR HR LV LI CH22BH BG GE DE IE MK RS GB23GI IL AE24MD PK RO SA SK ES SE TN VG DZ25CV MZ26IS TR IR FR GR IT MR MC SM BF CM MG28AL AZ CY DO GT HU LB PL BJ CI ML SN29BR PS QA UA30JO KW MU31MT')
    #                                    = search (with regexp) in this string (which are the lengths and countrycodes seperated by space)
    # Return the first found match (scroll to the right to see)                                                                                                                                                                                                                                .group(1)
    # i[:2]in                                                                                                                                                                                                                                                                                           or None
    # = The first two characters in the returned string (in the same order and same case)
    z=i[:2]in re.search(r'%s([A-Z ]*)'%k,'15NO16BE BI18DK FO FI GL NL19MK SI20AT BA ES KZ LT LU21CR HR LV LI CH22BH BG GE DE IE MK RS GB23GI IL AE24MD PK RO SA SK ES SE TN VG DZ25CV MZ26IS TR IR FR GR IT MR MC SM BF CM MG28AL AZ CY DO GT HU LB PL BJ CI ML SN29BR PS QA UA30JO KW MU31MT').group(1)or None
    if int(''.join([c if c.isdigit()else str(ord(c)-55)for c in i[4:]+i[:4]]))%97!=1 or z is None:return('Invalid')
    return(' '.join([i[0+j:4+j]for j in range(0,k,4)]))
chill0r
quelle
0

Perl (535)

Noch nicht wirklich Golf gespielt - keine Ahnung, ob ich mich für den Bonus qualifiziere ;-) Ich werde einige Erklärungen zum Typ @professorfish hinzufügen.

#!perl -ln
$r="15NO16BEBI18DKFIFOGLNL19MKSI20ATBAEEKZLTLU21CHCRHRLILV22BGBHDEGBGEIEMERS23AEGIIL24ADCZDZESMDPKROSASESKTNVG25AOCVMZPT26IRISTR27BFCMFRGRITMCMGMRSM28BJCICYDOGTHULBMLPLSNAZ29BRPSQAUA30JOKWMU31MT";
$c{$1} = [unpack("(A2)*", $2)] while($r) =~/(\d{2})(\D{2,})/g; 
@h{("A".."Z")}=(10..35);
chomp;$o=$_;$_=uc$_;
s/[ -.]//g;
$l=y///c;
($m)=($_=~m/^.{2}/g);
($n=$_) =~s/^(....)(.*)/$2$1/dg;
$n=~s/([A-Z])/$h{$1}/g;
print $m ~~ @{$c{$l}} ? "length valid for $m":"invalid length"; 
use bignum;
print $n%97==1 ? "$o ok":"$o Invalid";
G. Cito
quelle
0

JavaScript (Node.js) , 372 Byte * .75 = 279

s=>(s=s[R="replace"](/[^A-Z0-9]/g,"")).length-14-"NO|BEBI||DKFOFIGLNL|MKSI|BATEEKZLTLU|CRCHRLVLI|GBHBGEDEIEMERS|GILAE|SADCZMDZPKROSASKESETNVG|PTAOCVMZ|ISTRIR|BFRGRITSMRMCMG|ALBJAZCYDOGTHUPLCIMLSN|BRPSQAUA|JOKWMU|MT".match(eval(`/.*${s.slice(0,2)}/i`))[0].split`|`.length||BigInt((s.slice(4)+s.slice(0,4))[R](/\w/g,x=>parseInt(x,36)))%97n-1n?"Invalid":s[R](/(.{4})/g,"$1 ")

Probieren Sie es online aus!

Testfälle aus @marinus 'J-Antwort entlehnt.

Shieru Asakoto
quelle