monokey.scm 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. ;;;
  2. ;;; Monoalphabetic encipher and decipher
  3. ;;;
  4. ;;; Copyright 2016 Jason K. MacDuffie
  5. ;;; License: GPLv3+
  6. ;;;
  7. (define (key-to-full-key key-in)
  8. ;; First, add full alphabet to the end of key-in
  9. (define combined-key (append key-in (string->list "ABCDEFGHIJKLMNOPQRSTUVWXYZ")))
  10. ;; Then, remove duplicates from that result
  11. (let loop ((result '())
  12. (next combined-key))
  13. (if (null? next)
  14. (reverse result)
  15. (loop (if (member (car next) result)
  16. result
  17. (cons (car next) result))
  18. (cdr next)))))
  19. (define (mono-encipher pt-in key-in)
  20. (inner-mono-encipher pt-in (key-to-full-key key-in)))
  21. (define (mono-decipher pt-in key-in)
  22. (inner-mono-decipher pt-in (key-to-full-key key-in)))
  23. (define (inner-mono-encipher pt-in full-key-in)
  24. ;; Encipher pt-in with a monoalphabetic cipher, where
  25. ;; key-in is a list of the letters with which to replace
  26. ;; the plaintext letters.
  27. (define vector-key (list->vector full-key-in))
  28. (map (lambda (c) (vector-ref vector-key
  29. (letter->integer c)))
  30. pt-in))
  31. (define (inner-mono-decipher ct-in full-key-in)
  32. ;; Inverse of mono-encipher
  33. (define vector-key (make-vector 26))
  34. (let loop ((i 0)
  35. (in full-key-in))
  36. ;; We need to build the inverse key
  37. (when (< i 26)
  38. (vector-set! vector-key
  39. (letter->integer (car in))
  40. (integer->letter i))
  41. (loop (+ i 1) (cdr in))))
  42. (map (lambda (c) (vector-ref vector-key
  43. (letter->integer c)))
  44. ct-in))