(ns org.rosettacode.clojure.vigenere
  (:require [clojure.string:as string]))


(defn to-num [char] (- (int char) (int \A)))


(defn from-num [num] (char (+ (mod num 26) (int \A))))


(defn to-normalized-seq [str]
  (map #'first (re-seq #"[A-Z]" (string/upper-case str))))



(defn crypt1 [op text key] 
  (from-num (apply op (list (to-num text) (to-num key)))))

(defn crypt [op text key]
  (let [xcrypt1 (partial #'crypt1 op)]
    (apply #'str
      (map xcrypt1 (to-normalized-seq text) 
                   (cycle (to-normalized-seq key))))))


(defn encrypt [plaintext key] (crypt #'+ plaintext key))


(defn decrypt [ciphertext key] (crypt #'- ciphertext key))