Vigenère cipher: Difference between revisions
Content deleted Content added
Simpler D code |
→{{header|TXR}}: Extensions in TXR's lazy facilities make shorter work of this. |
||
Line 1,887: | Line 1,887: | ||
=={{header|TXR}}== |
=={{header|TXR}}== |
||
{{trans|Perl 6}} |
|||
Well, not exactly a translation but similar. The mapcar function vectorizes the operation over the characters, like Perl 6 hyper-operators. The repetition of the vigenere key is performed by a lazy list created by vig-pad. Perl 6 hyper-operators have this repetition behavior built-in, evidently. |
|||
<lang txr>@(next :args) |
<lang txr>@(next :args) |
||
@(do |
@(do |
||
(defun letter-mod26-op (func) ;; add or subtract capital letters modulo 26 |
|||
(defun str-to-list (str) |
|||
(for ((i 0) l) ((< i (length str)) (nreverse l)) ((inc i)) |
|||
(push (chr-str str i) l))) |
|||
(defun vig-pad (key) |
|||
(let ((i 0) (m (length key))) |
|||
(make-lazy-cons (lambda (lcons) |
|||
⚫ | |||
(rplacd lcons (make-lazy-cons (lcons-fun lcons))) |
|||
(set i (mod (+ i 1) m)))))) |
|||
(defun chrmod (func) |
|||
(lambda (a b) (+ #\A (mod (call func (- a #\A) (- b #\A)) 26)))) |
(lambda (a b) (+ #\A (mod (call func (- a #\A) (- b #\A)) 26)))) |
||
(defun vig (msg key encrypt) |
(defun vig (msg key encrypt) |
||
( |
(cat-str (mapcar (letter-mod26-op (if encrypt (fun +) (fun -))) |
||
(list-str msg) |
|||
⚫ | |||
@(coll)@{key /[A-Za-z]/}@(end) |
@(coll)@{key /[A-Za-z]/}@(end) |
||
@(coll)@{msg /[A-Za-z]/}@(end) |
@(coll)@{msg /[A-Za-z]/}@(end) |
||
Line 1,925: | Line 1,913: | ||
@(end)</lang> |
@(end)</lang> |
||
Here, the TXR pattern language is used to scan letters out of two arguments, and convert them to upper case. The embedded TXR Lisp dialect handles the Vigenère logic, in just a few lines of code. |
|||
⚫ | |||
The Vigenère substitution is driven by good old Lisp <code>mapcar</code> which works over the data represented as lists of characters (provided by applying the <code>list-str</code> function to the string inputs). |
|||
Now <code>mapcar</code> walks lists in parallel, stopping at the end of the shortest list. This traditional behavior of <code>mapcar</code> turns out to be a very good idea when you introduce infinite lazy lists into the mix. Infinite lists are longer than concrete lists and so mapcar keeps going until the shortest concrete list runs out. |
|||
We can represent the text to be enciphered or deciphered as a concrete list of the letters, and the Vigenère key as an infinite lazy list, giving us a key pad which consists of an infinite number of repetitions of the key. Such a list is produced by TXR Lisp's <code>repeat</code> operator, which takes a list and makes a lazy list out of repetitions of that list. |
|||
Then <code>mapcar</code> will zip the text and the infinite key pad two together, through the addition or subtraction operation. |
|||
TXR Lisp's <code>+</code> and <code>-</code> operators are generic over characters. An integer may be added to a character to produce a displacement through the code space to get to another character. When a character is subtracted from another, the result is an integer which is the difference between their codes. |
|||
⚫ | |||
text: BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH |
text: BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH |
||
key: VIGENERECIPHER |
key: VIGENERECIPHER |