Tulis validator IBAN

8

Tulis sebuah program (isi fungsinya cukup) yang menerima serangkaian karakter alfanumerik dan memvalidasinya sesuai dengan ISO 13616: 2007. Algoritma untuk validasi adalah (sumber: artikel wikipedia di IBAN http://en.wikipedia.org/wiki/International_Bank_Account_Number ):

Memvalidasi IBAN IBAN divalidasi dengan mengubahnya menjadi integer dan melakukan operasi mod-97 dasar (seperti yang dijelaskan dalam ISO 7064) di atasnya. Jika IBAN valid, sisanya sama dengan 1. Algoritma validasi IBAN adalah sebagai berikut:

  • Pastikan total panjang IBAN sudah benar sesuai negara. Jika tidak, IBAN tidak valid. Panjang IBAN yang benar dapat ditemukan di sini: http://pastebin.com/kp4eECVk (juga dapat ditemukan di bawah), dipesan berdasarkan panjang nomor IBAN. 2 karakter pertama dari setiap angka adalah kode negara. Semua karakter lain (huruf kecil pada pastebin, tetapi dapat berupa kasus apa pun dalam IBAN yang sebenarnya) di belakang 2 pertama dapat berupa karakter alfanumerik apa pun.
  • Pindahkan keempat karakter awal ke akhir string.
  • Ganti setiap huruf dalam string dengan dua digit, dengan demikian memperluas string, di mana A = 10, B = 11, ..., Z = 35.
  • Menafsirkan string sebagai bilangan bulat desimal dan menghitung sisa angka itu di divisi dengan 97

Jika sisanya adalah 1, tes digit periksa dilewati dan IBAN mungkin valid.

Contoh (Bank Inggris fiktif, kode sortir 12-34-56, nomor rekening 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

Algoritma moest mengembalikan true (atau nilai kebenaran) jika angka tersebut valid, dan false (atau nilai palsu) jika angka tidak valid sesuai dengan algoritma. Anda tidak perlu memeriksa apakah nomor itu benar-benar ada, hanya jika itu valid. Algoritme harus bekerja untuk masing-masing nomor IBAN berbeda yang disetujui yang disebutkan dalam artikel wikipedia di atas. Algoritma harus kompatibel dengan angka baik dengan atau tanpa karakter pemisah antara 2 karakter alfanumerik. Karakter pemisah dapat berupa titik, spasi atau tanda hubung dan satu angka dapat berisi berbagai jenis pemisah.

Lubang biasa berlaku: tidak ada sumber daya eksternal, tidak ada fungsi atau metode bawaan.

Jenis puzzle adalah kode golf. Kode terpendek dalam bytecount menang. Pelat standar yang diperlukan untuk menjalankan program (mis. Namespace, kelas, deklarasi fungsi dalam OOP) tidak termasuk dalam bytecount.

Bonus: jika Anda dapat mengembalikan nomor IBAN yang diformat dengan benar (sesuai dengan format nasional di wikipedia) alih-alih dalam kasus nomor yang valid, Anda mendapatkan pengurangan 25% dalam skor Anda. Jika nomor tidak valid, Anda mengembalikan string literal dengan nilai "Tidak Valid".


Salinan panjang IBAN dalam hal pastebin pernah dihapus:

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
sumber
3
Bagi siapa pun yang menyarankan untuk menambahkan tag perl dan python: tag bahasa dalam tantangan harus digunakan untuk membatasi tantangan pada bahasa tertentu (atau setidaknya, saya pikir itulah maksud mereka). Tantangan ini terbuka untuk semua bahasa. Karena itu, saya menolak hasil edit.
Nzall

Jawaban:

4

J (294 - 73.5 = 220.5)

Saya belum menghitung definisi fungsi ( f=:3 :0... )) karena dapat dianggap boilerplate, menghitung seluruh blok memberikan skor 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-.' -.'
)

Tes:

   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

Penjelasan:

  • b=.y-.' -.': hapus pemisah apa pun dari argumen dan simpan hasilnya di b .
  • 1}.;' '&,&.>_4<\b: pisahkan bdalam grup empat, tambahkan spasi di depan setiap grup, bergabung dengan grup dan hapus spasi di depan. Jika yberisi nomor IBAN yang valid, ini adalah representasi kanoniknya (yaitu kelompok empat, dipisahkan oleh spasi, dengan kelompok terakhir mungkin memiliki kurang dari empat elemen).
  • (... ){'Invalid';: buat array dengan string Invalidsebagai elemen 0 dan nomor IBAN yang diformat sebagai elemen 1. Pilih yang benar berdasarkan pada apakah nomor IBAN valid:

    • Periksa panjangnya:
      • 'NO.BEBI.---.JOKWU.MT.': daftar semua kode negara untuk setiap panjang, dipisahkan oleh titik-titik
      • +/"1(2{.b)&E.;.2: kelompokkan string berdasarkan titik-titik, dan lihat mana yang berisi kode negara yang diberikan (2 elemen pertama b).
      • 15+1 i.~: cari indeks yang cocok dan tambahkan 15untuk menemukan panjangnya.
      • (#b)=: periksa dengan panjang aktual b.
    • Periksa nomornya:
      • 4|.b: putar bke kiri sebanyak 4 (atur ulang)
      • k=.3&u:: cari nilai ASCII untuk setiap nomor
      • 48-~k-7*64<k: kurangi 7 dari setiap huruf, lalu kurangi 48 dari semua, berikan nilainya
      • 1".'x',~' '-.~":: memformat, menghapus spasi, menambahkan 'x' di akhir (untuk mode presisi tinggi, yang diperlukan untuk angka besar), dan mengubahnya kembali menjadi angka
      • 1=97|: periksa apakah angka mod 97 sama dengan 1.
  • >: unbox string yang dihasilkan
marinus
sumber
4

CJam, 151,5 141,75 poin

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*?

Program di atas adalah 189 byte dan memenuhi syarat untuk bonus.

Dengan biaya 26 byte lebih - untuk skor total 161,25 - kita dapat menghindari karakter yang tidak patut:

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*?

Anda dapat menguji versi ini dalam juru bahasa CJam .

Contoh dijalankan

$ 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

Bagaimana itu bekerja

"…"256b27b'@f+"

mengubah string "…"menjadi bilangan bulat dengan menganggapnya sebagai basis-256 angka, kemudian menjadi array bilangan bulat dengan menganggapnya sebagai basis 27-angka, menambahkan kode karakter@ untuk setiap digit dan melemparkan ke Karakter dalam proses.

Akibatnya, kode berikut dijalankan:

" 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
sumber
LANG=en_US java -jar cjam-0.6.2.jar iban.cjam<<<GB82WEST12345698765432output Tidak Valid, apa yang saya lakukan salah (berjalan pada Windows8.1 dan Cygwin)?
@professorfish: Saya tidak punya komputer Windows, jadi saya tidak bisa memeriksa dari sini, tapi mari kita mulai dengan memverifikasi yang berikut: 1. Apakah iban.cjam berhasil dihasilkan? md5sum iban.cjamharus dicetak 1960c33e31ae5646cd0400826757b3bc. 2. Apakah lokal diinstal dengan benar? Anda dapat memeriksa dengan mengeksekusi locale -a | grep en_US.
Dennis
Itu belum dihasilkan dengan benar ( fb620d509887f1a7298c3e5ff312401a). locale -a|grep en_USoutput en_USdanen_US.utf8
@professorfish: Menarik. Anda bisa mencoba ini untuk menghindari file iban.cjam: LANG=en_US cjam <(LANG=en_US cjam gen.cjam) <<< GB82WEST12345698765432. Saya telah memasukkan versi ASCII saja dalam jawaban saya yang seharusnya lebih mudah diverifikasi.
Dennis
2

Pesta, 738 519 444 434 427

Ini adalah sesuatu untuk memulai kita, saya menulisnya (dan menyimpan 317 karakter, sebagian besar dalam bit penyimpanan kode negara) sementara pertanyaannya ada di kotak pasir. Beri tahu saya jika ada masalah.

Fungsi membaca dari stdin, yang cukup umum di Bash (pertanyaannya mengatakan "menerima serangkaian karakter alfanumerik", tidak memerlukan ini melalui argumen).

Mengembalikan 0 jika IBAN valid dan nilai bukan nol jika tidak valid.

IBAN yang mengandung karakter apa pun selain pembatas . -dan A-Z0-9tidak valid

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`

Penjelasan

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`

Contohnya

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

sumber
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
sumber
WT ?? - itu golf! Kerja bagus. Itu terlihat agak seperti garis kebisingan dari kejauhan ... j / k selain itu pelengkap ;-)
G. Cito
2

Perl (356 + 2 * 75% = 268.5)

kode ini sangat membingungkan sehingga penyorotan sintaksis SE pun hilang di dalamnya :)

#!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]

Penjelasan

#!perl -nl

-nberarti membaca stdin baris demi baris; -lmenambahkan baris baru untuk dicetak

use bignum;

diperlukan untuk operasi modulo nanti untuk mengembalikan nilai yang benar.

s/\W//g;

hapus semua yang bukan dari IBAN.

$_=$T=uc;

konversikan nomor iban menjadi huruf besar, juga simpan ke $ T - akan digunakan untuk pencetakan cantik nanti.

$q=15;

atur variabel sementara ke 15, itu akan digunakan untuk membangun tabel hash dengan kode negara untuk pemetaan panjang iban.

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

pisahkan string besar menjadi array koma atau kode negara dua huruf, iterate di atasnya. jika elemen dimulai dengan huruf, ini adalah kode negara - simpan dalam hash dengan nilai $ q; jika tidak, koma berarti menambah $ q. jadi, TIDAK akan mendapatkan nilai 15, BE dan BI akan menjadi 16, dan seterusnya.

/../;

cocokkan dua karakter pertama dari IBAN (kode negara)

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

periksa apakah IBAN memiliki panjang yang benar untuk kode negara, simpan hasil dalam $ q

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

pindahkan empat karakter pertama ke akhir IBAN

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

ganti semua huruf dengan angka yang sesuai, dimulai dengan A = 10

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

cetak "Tidak Valid" atau IBAN yang tercetak cantik. 1==$_%97*$qhanya akan sama 1dengan IBAN dengan panjang yang benar dan sisa yang benar.

perl Cina goth
sumber
1
bagus! Di perlsubkontest "hanya" Anda menang ;-) Meskipun membingungkan, bisakah Anda mencoba menjelaskannya sedikit seperti pada contoh bash? Cukup cantik ?! Jika Anda menjelaskan milik Anda, saya akan menjelaskan milik saya :-) (meskipun saya mungkin mencuri salah satu trik Anda yang sebenarnya, panjang negara IBAN dulu). Bersulang.
G. Cito
2

Perl 6 - 354 karakter - (tidak yakin bonus)

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";
}

Masukan bacaan dari IBANS.txt pada STDINdan menghirup aturan dari file ir(saya meninggalkan aturan dari total jika mereka boilerplate - file aturan adalah 191 karakter sehingga total akan menjadi 545.

 perl6 ibanvalidate.p6 IBANS.txt

IBANS.txt adalah sebagai berikut:

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

Catatan

  • memvalidasi kode negara dan panjang dan keluaran seperti di bawah ini
  • Karakter dihitung dari: wc -m ibanvalidate.p6
  • Saat ini tidak banyak pengecekan kesalahan validasi input dilakukan.
  • Whitespace signifikan dalam Perl6 (atau lebih signifikan dari Perl 5) sehingga dihitung.

Output khas:

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

Ini bukan kode Perl6 yang khas (terutama the comb- lines yang dikembangkan oleh Perl yang ramah dan berpengaruh ini): Saya seorang pemula. Setelah kontes selesai, saya akan menambah / mengubah dan membuat modifikasi yang disarankan oleh Perl6-ers. Terima kasih telah bermain dan bersikap baik :-)

G. Cito
sumber
Di mana memeriksa kode negara?
@professorfish ... Saya melakukan itu di versi yang salah dari perl ;-) itu akan menambah 200+ lebih banyak karakter saya yakin.
G. Cito
1

Perl 6 , 311 byte, skor 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/\ .-//}

Cobalah online!

Saya tidak yakin

  • di mana karakter pemisah diperbolehkan persis. Saya cukup menghapus semuanya.
  • apakah hasil akhir yang diformat harus huruf besar.

Penjelasan

{
  /                # 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
sumber
0

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

(Bisa dikatakan pertama: Saya agak bingung apa yang HARUS dihitung dengan aturan Anda jadi saya hanya menghitung seluruh fungsi saya)

539 karakter - Termasuk importdan def IBAN(i):(tab di awal baris dihitung tetap dengan python sehingga tidak masalah)

Bonus diterapkan sebagaimana tercantum dalam aturan.

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)]))

Kode dengan komentar (belum selesai ... Saya terlalu lelah untuk menulis bagian komentar yang tersisa ... Saya akan melakukannya besok)

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)]))
dinginkan
sumber
0

Perl (535)

Belum benar-benar bermain golf - tidak tahu apakah saya memenuhi syarat untuk mendapatkan bonus ;-) Saya akan menambahkan beberapa penjelasan jenis @professorfish.

#!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
sumber
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 ")

Cobalah online!

Kasus uji dipinjam dari jawaban J @marinus.

Shieru Asakoto
sumber