## IBAN

### October 25, 2019

This is tedious, but not hard in a language that supports big-integer arithmetic. First we convert the string to a large integer:;

(define (iban str) (let-values (((start end) (split 4 (string->list str)))) (let loop ((cs (append end start)) (zs (list))) (cond ((null? cs) (string->number (list->string (flatten (reverse zs))))) ((char-alphabetic? (car cs)) (loop (cdr cs) (cons (string->list (number->string (- (char->integer (car cs)) 55))) zs))) (else (loop (cdr cs) (cons (car cs) zs)))))))

Then it is easy to validate an IBAN or generate a hash code:

(define (valid? str) (= 1 (modulo (iban str) 97)))

(define (gen str) (- 98 (modulo (iban str) 97)))

Here are the example problems:

> (valid? "GB82WEST12345698765432")

#t

> (gen “GB00WEST12345698765432”)

82

You can run the program at https://ideone.com/k7S3Rg, but that calculates the answers incorrectly because the version of Chicken Scheme at ideone doesn’t compute big integers properly.

Python 3.8 solution:

Used as follows:

Here is a simple solution in R7R6 Scheme and a few helpers from

popular SRFIs.

It emphasizes clarity over efficiency and makes rather liberal use of

potentially expensive string operations and conversions. On the other

hand, given the fixed size and format of IBAN, it is a Theta(1)

solution.

It also allows human-friendly spaces (and potentially other

punctuation) in the IBANs.

Output:

I’m not going to try to compete with Alex’s nicely engineered solution, so here’s a Python two-liner (it would go into one, but it feels like cheating to go over 80 chars in a line):

And in fact, we can use the Python string -> int conversion with base 36 and get an under 80 chars one-liner (I got this from the Rosetta Code IBAN page):

A Haskell version.

When I tried to run your solution in Gambit Scheme, I got the following:

(define-syntax let-values

(syntax-rules ()

((_ () f1 f2 …) (let () f1 f2 …))

((_ ((fmls1 expr1) (fmls2 expr2) …) f1 f2 …)

(let-values-help fmls1 () () expr1 ((fmls2 expr2) …) (f1 f2 …)))))

*** ERROR IN (console)@56.17 — Ill-formed expression

3> (define-syntax let-values-help

(syntax-rules ()

((_ (x1 . fmls) (x …) (t …) e m b)

(let-values-help fmls (x … x1) (t … tmp) e m b))

((_ () (x …) (t …) e m b)

(call-with-values

(lambda () e)

(lambda (t …)

(let-values m (let ((x t) …) . b)))))

((_ xr (x …) (t …) e m b)

(call-with-values

(lambda () e)

(lambda (t … . tmpr)

(let-values m (let ((x t) … (xr tmpr)) . b)))))))

*** ERROR IN (console)@61.17 — Ill-formed expression

Here’s a solution in C.

Example usage:

`calc_hash`

is not a fitting name for the function above. I think that reflects my original intent, although the function calculates a remainder, not a hash.