; IBAN

(define (split n xs)
	(let loop ((n n) (xs xs) (zs '()))
	  (if (or (zero? n) (null? xs))
	      (values (reverse zs) xs)
	      (loop (- n 1) (cdr xs) (cons (car xs) zs)))))

(define (flatten xs)
	(cond ((null? xs) xs)
	      ((pair? xs)
	        (append (flatten (car xs))
	                (flatten (cdr xs))))
	      (else (list xs))))

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

(define (valid? str) (= 1 (modulo (iban str) 97)))
(define (gen str) (- 98 (modulo (iban str) 97)))

(display (valid? "GB82WEST12345698765432")) (newline)
(display (gen "GB00WEST12345698765432")) (newline)