Viết trình xác nhận IBAN


8

Viết chương trình (phần thân của hàm là đủ) chấp nhận một chuỗi các ký tự chữ và số và xác nhận nó theo ISO 13616: 2007. Thuật toán để xác thực là (nguồn: bài viết trên wikipedia về IBAN http://en.wikipedia.org/wiki/I quốc_Bank_Account_Number ):

Xác thực IBAN Một IBAN được xác thực bằng cách chuyển đổi nó thành một số nguyên và thực hiện thao tác mod-97 cơ bản (như được mô tả trong ISO 7064) trên nó. Nếu IBAN hợp lệ, phần còn lại bằng 1. Thuật toán xác thực IBAN như sau:

  • Kiểm tra xem tổng chiều dài IBAN có đúng theo quốc gia không. Nếu không, IBAN không hợp lệ. Độ dài IBAN chính xác có thể được tìm thấy ở đây: http://pastebin.com/kp4eECVk (cũng có thể được tìm thấy bên dưới), được sắp xếp theo độ dài của số IBAN. 2 ký tự đầu tiên của mỗi số là mã quốc gia. Tất cả các ký tự khác (chữ cái viết thường trên pastebin, nhưng có thể là bất kỳ trường hợp nào trong IBAN thực tế) đằng sau 2 ký tự đầu tiên có thể là bất kỳ ký tự chữ và số nào.
  • Di chuyển bốn ký tự ban đầu đến cuối chuỗi.
  • Thay thế mỗi chữ cái trong chuỗi bằng hai chữ số, từ đó mở rộng chuỗi, trong đó A = 10, B = 11, ..., Z = 35.
  • Giải thích chuỗi dưới dạng một số nguyên thập phân và tính phần còn lại của số đó khi chia cho 97

Nếu phần còn lại là 1, kiểm tra chữ số kiểm tra được thông qua và IBAN có thể hợp lệ.

Ví dụ (ngân hàng Vương quốc Anh hư cấu, mã sắp xếp 12-34-56, số tài khoản 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

Thuật toán moest trả về true (hoặc giá trị trung thực) nếu số đó hợp lệ và sai (hoặc giá trị giả) nếu số đó không hợp lệ theo thuật toán. Bạn không cần kiểm tra xem con số có thực sự tồn tại hay không, chỉ khi nó hợp lệ. Thuật toán phải hoạt động cho từng số IBAN được phê duyệt khác nhau được đề cập trong bài viết trên wikipedia ở trên. Thuật toán phải tương thích với các số cả có hoặc không có ký tự phân cách giữa 2 ký tự chữ và số. Ký tự dấu phân cách có thể là dấu chấm, dấu cách hoặc dấu gạch ngang và một số có thể chứa các loại dấu phân cách khác nhau.

Các lỗ hổng thông thường được áp dụng: không có tài nguyên bên ngoài, không có chức năng hoặc phương thức tích hợp.

Loại câu đố là mã golf. Mã ngắn nhất trong chiến thắng bytecount. Bản tóm tắt chuẩn cần thiết để thực thi chương trình (ví dụ: không gian tên, lớp, khai báo hàm trong OOP) không được bao gồm trong bytecount.

Phần thưởng: nếu bạn có thể trả về số IBAN được định dạng chính xác (theo định dạng quốc gia trên wikipedia) thay vì đúng trong trường hợp số hợp lệ, bạn sẽ được giảm 25% số điểm của mình. Nếu số không hợp lệ, bạn trả về một chuỗi ký tự có giá trị "Không hợp lệ".


Bản sao độ dài IBAN trong trường hợp pastebin bị xóa:

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

3
Đối với bất cứ ai đề nghị thêm thẻ perl và python: thẻ ngôn ngữ trong các thử thách nên được sử dụng để giới hạn thách thức đối với một ngôn ngữ nhất định (hoặc ít nhất, tôi nghĩ đó là ý định của chúng). Thách thức này là mở cho tất cả các ngôn ngữ. Như vậy, tôi đã từ chối chỉnh sửa.
Nzall

Câu trả lời:


4

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

Tôi đã không tính định nghĩa hàm ( f=:3 :0... )) bởi vì nó có thể được coi là bản tóm tắt, đếm toàn bộ khối cho điểm 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-.' -.'
)

Các xét nghiệm:

   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

Giải trình:

  • b=.y-.' -.': xóa bất kỳ dấu phân tách nào khỏi đối số và lưu kết quả vào b.
  • 1}.;' '&,&.>_4<\b: chia bthành các nhóm bốn, thêm một khoảng trắng ở trước mỗi nhóm, tham gia các nhóm và xóa khoảng trắng hàng đầu. Nếu ychứa một số IBAN hợp lệ, đây là đại diện chính tắc của nó (tức là các nhóm bốn, được phân tách bằng dấu cách, với nhóm cuối cùng có thể có ít hơn bốn phần tử).
  • (... ){'Invalid';: Tạo một mảng với chuỗi Invalidlà phần tử 0 và số IBAN được định dạng là phần tử 1. Chọn đúng một phần dựa trên việc số IBAN có hợp lệ không:

    • Kiểm tra độ dài:
      • 'NO.BEBI.---.JOKWU.MT.': danh sách tất cả các mã quốc gia cho mỗi độ dài, được phân tách bằng dấu chấm
      • +/"1(2{.b)&E.;.2: nhóm chuỗi theo dấu chấm và xem cái nào chứa mã quốc gia đã cho (2 phần tử đầu tiên của b).
      • 15+1 i.~: tìm chỉ mục của kết quả khớp và thêm 15để tìm độ dài.
      • (#b)=: kiểm tra nó so với chiều dài thực tế của b.
    • Kiểm tra số:
      • 4|.b: xoay bsang trái theo 4 (sắp xếp lại)
      • k=.3&u:: tìm giá trị ASCII cho mỗi số
      • 48-~k-7*64<k: trừ 7 từ mỗi chữ cái, sau đó trừ 48 từ tất cả, đưa ra các giá trị
      • 1".'x',~' '-.~":: định dạng, xóa khoảng trắng, thêm 'x' ở cuối (đối với chế độ có độ chính xác cao, cần thiết cho số lớn) và biến nó trở lại thành số
      • 1=97|: kiểm tra xem số mod 97 có bằng 1 không.
  • >: bỏ hộp chuỗi kết quả

4

CJam, 151,5 141,75 điểm

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

Chương trình trên dài 189 byte và đủ điều kiện nhận thưởng.

Với chi phí thêm 26 byte - với tổng số điểm là 161,25 - chúng tôi có thể tránh các ký tự không thể in được:

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:o48u_2EKgyG@.V"33f-94b27b'@f+'@/{Q2<#1&!}#_W>F*+=Q4m<A,s'[,65>+f#s~97%1=]1-"Invalid"Q4/S*?

Bạn có thể kiểm tra phiên bản này trong trình thông dịch CJam .

Chạy ví dụ

$ 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

Làm thế nào nó hoạt động

"…"256b27b'@f+"

chuyển đổi chuỗi "…"thành một số nguyên bằng cách coi nó là số cơ sở 256, sau đó thành một mảng số nguyên bằng cách coi đó là số cơ sở 27, thêm mã ký tự của @mỗi chữ số và chuyển thành Ký tự trong quá trình.

Kết quả là đoạn mã sau được thực thi:

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

LANG=en_US java -jar cjam-0.6.2.jar iban.cjam<<<GB82WEST12345698765432đầu ra Không hợp lệ, tôi đang làm gì sai (chạy trên Windows8.1 và Cygwin)?

@professorfish: Tôi không có máy tính Windows, vì vậy tôi không thể kiểm tra từ đầu này, nhưng hãy bắt đầu bằng cách xác minh những điều sau: 1. iban.cjam có được tạo thành công không? md5sum iban.cjamnên in 1960c33e31ae5646cd0400826757b3bc. 2. Địa điểm được cài đặt đúng cách? Bạn có thể kiểm tra bằng cách thực hiện locale -a | grep en_US.
Dennis

Nó không được tạo đúng ( fb620d509887f1a7298c3e5ff312401a). locale -a|grep en_USđầu ra en_USen_US.utf8

@professorfish: Thú vị. Bạn có thể thử điều này để tránh tệp iban.cjam : LANG=en_US cjam <(LANG=en_US cjam gen.cjam) <<< GB82WEST12345698765432. Tôi đã bao gồm một phiên bản chỉ ASCII trong câu trả lời của mình để dễ xác minh hơn.
Dennis

2

Bash, 738 519 444 434 427

Đây là một cái gì đó để bắt đầu với chúng tôi, tôi đã viết nó (và lưu được 3,8 ký tự, chủ yếu là trong bit lưu trữ mã quốc gia) trong khi câu hỏi nằm trong hộp cát. Hãy cho tôi biết nếu có bất kỳ vấn đề.

Hàm đọc từ stdin, khá phổ biến trong Bash (câu hỏi cho biết "chấp nhận một chuỗi các ký tự chữ và số", nó không yêu cầu điều này phải thông qua các đối số).

Nó trả về 0 nếu IBAN hợp lệ và giá trị khác không nếu nó không hợp lệ.

IBAN chứa bất kỳ ký tự nào ngoài dấu phân cách . -A-Z0-9không hợp lệ

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`

Giải trình

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`

Ví dụ

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

2

Con trăn 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

WT ?? - đó là một số golf! Công việc tốt đẹp. Nó trông giống như tiếng ồn đường truyền từ xa ... j / k bên cạnh đó là phần bù ;-)
G. Cito

2

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

mã này khó hiểu đến nỗi ngay cả cú pháp tô sáng của SE cũng bị mất trong đó :)

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

Giải trình

#!perl -nl

-ncó nghĩa là đọc dòng stdin theo dòng; -lthêm dòng mới để in

use bignum;

cần thiết cho hoạt động modulo sau này để trả về giá trị chính xác.

s/\W//g;

xóa mọi thứ không phải là từ IBAN.

$_=$T=uc;

chuyển đổi số iban thành chữ hoa, đồng thời lưu nó thành $ T - sẽ được sử dụng để in đẹp sau này.

$q=15;

đặt biến tạm thời thành 15, nó sẽ được sử dụng để xây dựng bảng băm với mã quốc gia thành ánh xạ độ dài iban.

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

chia chuỗi lớn thành một mảng các dấu phẩy hoặc mã quốc gia gồm hai chữ cái, lặp lại trên nó. nếu phần tử bắt đầu bằng một chữ cái, thì đó là mã quốc gia - lưu nó trong hàm băm với giá trị $ q; mặt khác, dấu phẩy có nghĩa là tăng $ q. vì vậy, NO sẽ nhận được giá trị 15, BE và BI sẽ là 16, v.v.

/../;

khớp hai ký tự đầu tiên từ IBAN (mã quốc gia)

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

kiểm tra xem IBAN có độ dài chính xác cho mã quốc gia hay không, lưu kết quả bằng $ q

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

di chuyển bốn ký tự đầu tiên đến cuối IBAN

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

thay thế tất cả các chữ cái bằng các số tương ứng, bắt đầu bằng A = 10

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

in "Không hợp lệ" hoặc IBAN được in đẹp. 1==$_%97*$qsẽ chỉ bằng 1với một IBAN có độ dài chính xác và phần còn lại đúng.


1
đẹp! Trong hợp đồng phụ " perlduy nhất" bạn giành chiến thắng ;-) Mặc dù khó hiểu, bạn có thể thử giải thích một chút như trong ví dụ bash không? Khá vui lòng?! Nếu bạn giải thích của bạn, tôi sẽ giải thích cho tôi :-) (mặc dù tôi có thể đánh cắp một trong những mánh khóe của bạn trước tiên là quốc gia có chiều dài IBAN). Chúc mừng.
G. Cito

2

Perl 6 - 354 ký tự - (không chắc chắn về tiền thưởng)

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

Đọc đầu vào từ IBANS.txttrên STDINvà slurping các quy tắc từ tập tin ir(tôi rời các quy tắc trên tổng số trong trường hợp họ đã soạn sẵn - các tập tin quy tắc là 191 ký tự như vậy tổng số sẽ là 545.

 perl6 ibanvalidate.p6 IBANS.txt

IBANS.txt là như sau:

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

Ghi chú

  • xác nhận mã quốc gia và độ dài và đầu ra như dưới đây
  • Số lượng nhân vật từ: wc -m ibanvalidate.p6
  • Hiện tại không có nhiều lỗi kiểm tra xác nhận đầu vào được thực hiện.
  • Khoảng trắng là dấu hiệu trong Perl6 (hoặc quan trọng hơn Perl 5) vì vậy được tính.

Sản lượng tiêu biểu:

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

Đây không phải là mã Perl6 điển hình (đặc biệt là comb- một nhà phát triển Perl thân thiện và có ảnh hưởng đã đề cập đến vấn đề này): Tôi là người mới bắt đầu. Khi cuộc thi kết thúc, tôi sẽ thêm / thay đổi và thực hiện bất kỳ sửa đổi nào được đề xuất bởi Perl6-ers. Cảm ơn bạn đã chơi và trở nên tốt đẹp :-)


Kiểm tra mã quốc gia ở đâu?

@professorfish ... Tôi đã làm điều đó trong phiên bản sai của perl ;-) nó sẽ thêm 200 ký tự nữa.
G. Cito

1

Perl 6 , 311 byte, điểm 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/\ .-//}

Hãy thử trực tuyến!

tôi không chắc

  • trong đó các ký tự phân cách được cho phép chính xác. Tôi chỉ đơn giản là loại bỏ tất cả chúng.
  • liệu đầu ra được định dạng cuối cùng có nên viết hoa hay không.

Giải trình

{
  /                # 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
}

0

Python3.x (539 ký tự - 25% = 404,25)

(Phải nói trước: Tôi hơi bối rối về những gì đã được tính theo quy tắc của bạn nên tôi chỉ đếm toàn bộ chức năng của mình)

539 ký tự - Bao gồm importdef IBAN(i):(các tab ở đầu dòng được tính bằng python để chúng không thành vấn đề)

Tiền thưởng áp dụng như đã nêu trong các quy tắc.

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

Mã với các bình luận (chưa hoàn thành ... Tôi quá mệt mỏi để viết phần còn lại của các bình luận ... Tôi sẽ làm điều đó vào ngày mai)

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

0

Perl (535)

Chưa thực sự chơi gôn - không biết tôi có đủ điều kiện nhận tiền thưởng hay không ;-) Tôi sẽ thêm một số giải thích loại @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";

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

Hãy thử trực tuyến!

Các trường hợp thử nghiệm mượn từ câu trả lời J của @marinus.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.