; affine-shift cipher

(define (inverse x n)
  (let loop ((x (modulo x n)) (a 1))
    (cond ((zero? x) (return #f))
          ((= x 1) a)
          (else (let ((q (- (quotient n x))))
                  (loop (+ n (* q x)) (modulo (* q a) n)))))))

(define (c->int c)
  (- (char->integer c) 65))

(define (int->c i)
  (integer->char (+ i 65)))

(define (cipher a b)
  (lambda (x)
    (modulo (+ (* a x) b) 26)))

(define (plain a b)
  (lambda (x)
    (modulo (* (inverse a 26) (- x b)) 26)))

(define (mapping func text)
  (list->string
    (map int->c
      (map func
        (map c->int
          (string->list text))))))

(define (encipher a b text)
  (mapping (cipher a b) text))

(define (decipher a b text)
  (mapping (plain a b) text))

(display (encipher 5 8 "PROGRAMMINGPRAXIS")) (newline)
(display (decipher 5 8 "FPAMPIQQWVMFPITWU")) (newline)