Deutsch   English   Français   Italiano  
<v4pktn$nlmm$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: "B. Pym" <No_spamming@noWhere_7073.org>
Newsgroups: comp.lang.lisp
Subject: Vigenere
Date: Mon, 17 Jun 2024 15:32:12 -0000 (UTC)
Organization: A noiseless patient Spider
Lines: 153
Message-ID: <v4pktn$nlmm$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Injection-Date: Mon, 17 Jun 2024 17:32:12 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="90b6bfd3931bdb2bad5411c6c3dc2474";
	logging-data="775894"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18+tY9ZNqbtLeMTR3zgnDCQ"
User-Agent: XanaNews/1.18.1.6
Cancel-Lock: sha1:joWL7wuDUs5bLh/rAKV9EwXSqn4=
Bytes: 5784

Pascal J. Bourguignon wrote:

> tristanhennequin <tristanhennequin@free.fr> writes:
> 
> > Hello,
> > I 've just read the vigenere implementation published on rosetta code :
> > 
> > I think it's very long and maybe clumsy.
> 
> It's also wrong.
> 
> > (defun strip (s)
> >   (remove-if-not
> >     (lambda (c) (char<= #\A c #\Z))
> >     (string-upcase s)))
> 
> There may be non alphabetic characters between A and Z.  This functions
> rightfully doesn't use alpha-char-p, (because alpha-char-p may contain
> implementation defined characters), but it is wrong in using this simple
> comparison.  Since we only want letters from A to Z, we must write it
> explicitely (or, possibly check that only letters from A to Z are
> between A and Z, but I have my doubts if this check can be done at
> compilation time).
> 
> So:
> 
> (defparameter alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
> 
> (defun strip (s) 
>   (remove-if-not (lambda (c) (find (char-upcase c) alphabet)) s)
> 
> 
> 
> > (defun vigenère (s key &key decipher
> > 			&aux (A (char-code #\A))
> > 			     (op (if decipher #'- #'+)))
> 
> Personnally, I don't like using &aux for stylistic reasons (it puts in
> the signature of the function details that belong to the implementation.
> It's very rare to find a case where having those variable in the
> signature is justified.  &aux is basically a ugly hack to do stuff in
> struct constructors).
> 
> 
> >   (labels
> >     ((to-char (c) (code-char (+ c A)))
> >      (to-code (c) (- (char-code c) A)))
> 
> Again, this part makes a lot of assumptions that may be wrong.  A better
> implementation is:
> 
>       (to-char (code) (aref     code alphabet))
>       (to-code (char) (position char alphabet))
> 
> >     (let ((k (map 'list #'to-code (strip key))))
> >       (setf (cdr (last k)) k)
> >       (map 'string
> > 	   (lambda (c)
> > 	     (prog1
> > 	       (to-char
> > 		 (mod (funcall op (to-code c) (car k)) 26))
> > 	       (setf k (cdr k))))
> > 	   (strip s)))))
> 
> This is not bad.  What you can do here, is to use pop:
> 
>     (map 'string
>            (lambda (c) (to-char (mod (funcall op (to-code c) (pop k)) 26)))
>            (strip s))
> 
> 
> > (let* ((msg "Beware the Jabberwock... The jaws that... the claws that
> > catch!")
> >        (key "vigenere cipher")
> >        (enc (vigenère msg key))
> >        (dec (vigenère enc key :decipher t)))
> >   (format t "msg: ~a~%enc: ~a~%dec: ~a~%" msg enc dec))
> > 
> > 
> 
> > What is the most concise and short version of the vigenere encryption
> > method can you produce in lisp?
> 
> (defparameter alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
> 
> (defun strip-non-letters (string) 
>   (remove-if-not (lambda (c) (find (char-upcase c) alphabet)) string))
> 
> (defun ensure-circular (list)
>   (setf (cdr (last list)) list))
> 
> (defun vigenère (text key &key decipher)  
>   (flet ((to-char (code) (aref     alphabet code))
>          (to-code (char) (position char alphabet :test (function char-equal))))
>     (declare (inline to-char to-code))
>     (let ((op      (if decipher (function -) (function +)))
>           (offsets (ensure-circular (map 'list (function to-code) (strip-non-letters key)))))
>       (map 'string
>            (lambda (c) (to-char (mod (funcall op (to-code c) (pop offsets)) 26)))
>            (strip-non-letters text)))))
> 
>   (let* ((msg "Beware the Jabberwock... The jaws that... the claws that catch!")
>          (key "vigenere cipher")
>          (enc (vigenère msg key))
>          (dec (vigenère enc key :decipher t)))
>     (format t "msg: ~a~%enc: ~a~%dec: ~a~%" msg enc dec))
> 
> 
> msg: Beware the Jabberwock... The jaws that... the claws that catch!
> enc: WMCEEIKLGRPIFVMEUGXXYILILZXYVBZLRGCEYAIOEKXIZGU
> dec: BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH
> --> nil

Gauche Scheme

(use srfi-1) ;; circular-list

(define alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ")

(define (text->list str)
  (filter-map
    (lambda (c) 
      (let ((x (char-upcase c))) (string-scan alphabet x)))
    (string->list str)))

(define (list->text lst)
  (list->string
    (map
      (lambda (n) (string-ref alphabet n))
      lst)))
  
(define (vig text key encrypt?)
  (list->text 
    (map
      (lambda(n k) (mod ((if encrypt? + -) n k) 26))
      (text->list text)
      (apply circular-list (text->list key)))))

(vig "Beware the Jabberwock... The jaws that... the claws that catch!"
  "vigenere cipher" #t)
  ===>
"WMCEEIKLGRPIFVMEUGXXYILILZXYVBZLRGCEYAIOEKXIZGU"

(vig "WMCEEIKLGRPIFVMEUGXXYILILZXYVBZLRGCEYAIOEKXIZGU"
  "vigenere cipher" #f)
  ===>
"BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH"

(vig "W M C E EIKLGRPIFVMEUGXXYILILZXYVBZLRGCEYAIOEKXIZGU"
  "vigenere cipher" #f)
  ===>
"BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH"