; autokey
(define (filter pred? xs)
(let loop ((xs xs) (ys '()))
(cond ((null? xs) (reverse ys))
((pred? (car xs))
(loop (cdr xs) (cons (car xs) ys)))
(else (loop (cdr xs) ys)))))
(define (plus a b)
(define (f a) (- (char->integer (char-upcase a)) 65))
(integer->char (+ (modulo (+ (f a) (f b)) 26) 65)))
(define (minus a b)
(define (f a) (- (char->integer (char-upcase a)) 65))
(integer->char (+ (modulo (- (f a) (f b)) 26) 65)))
(define (clean text)
(list->string
(filter char-alphabetic?
(string->list text))))
(define (encipher key text)
(let ((text (clean text)))
(let loop ((ks (string->list (string-append key text)))
(ts (string->list text)) (cs '()))
(if (null? ts)
(list->string (reverse cs))
(let ((c (plus (car ts) (car ks))))
(loop (cdr ks) (cdr ts) (cons c cs)))))))
(define (decipher key text)
(let loop ((ks (string->list key)) (ts (string->list text)) (cs '()))
(if (null? ts)
(list->string (reverse cs))
(let ((c (minus (car ts) (car ks))))
(loop (append (cdr ks) (list c)) (cdr ts) (cons c cs))))))
(display (encipher "PRAXIS" "a collection of etudes")) (newline)
(display (decipher "PRAXIS" "PTOITWCVWZYSHXBIQSX")) (newline)