Function: decipher-analyze-buffer
decipher-analyze-buffer is a byte-compiled function defined in
decipher.el.gz.
Signature
(decipher-analyze-buffer)
Documentation
Perform frequency analysis and store results in statistics buffer.
Creates the statistics buffer if it doesn't exist.
Source Code
;; Defined in /usr/src/emacs/lisp/play/decipher.el.gz
(defun decipher-analyze-buffer ()
"Perform frequency analysis and store results in statistics buffer.
Creates the statistics buffer if it doesn't exist."
(let ((decipher--prev-char (if decipher-ignore-spaces ?\s ?\*))
(decipher--before (make-vector 26 nil))
(decipher--after (make-vector 26 nil))
(decipher--freqs (make-vector 26 0))
(total-chars 0)
decipher--digram decipher--digram-list freq-list)
(message "Scanning buffer...")
(let ((i 26))
(while (>= (cl-decf i) 0)
(aset decipher--before i (make-vector 27 0))
(aset decipher--after i (make-vector 27 0))))
(if decipher-ignore-spaces
(progn
(decipher-loop-no-breaks #'decipher--analyze)
;; The first character of ciphertext was marked as following a space:
(let ((i 26))
(while (>= (cl-decf i) 0)
(aset (aref decipher--after i) 26 0))))
(decipher-loop-with-breaks #'decipher--analyze))
(message "Processing results...")
(setcdr (last decipher--digram-list 2) nil) ;Delete the phony "* " digram
;; Sort the digram list by frequency and alphabetical order:
(setq decipher--digram-list (sort (sort decipher--digram-list
(lambda (a b) (string< (car a) (car b))))
(lambda (a b) (> (cdr a) (cdr b)))))
;; Generate the frequency list:
;; Each element is a list of 3 elements (LETTER FREQ DIFFERENT),
;; where LETTER is the ciphertext character, FREQ is the number
;; of times it occurs, and DIFFERENT is the number of different
;; letters it appears next to.
(let ((i 26))
(while (>= (cl-decf i) 0)
(setq freq-list
(cons (list (+ i ?A)
(aref decipher--freqs i)
(decipher--digram-total (aref decipher--before i)
(aref decipher--after i)))
freq-list)
total-chars (+ total-chars (aref decipher--freqs i)))))
;; Switch to statistics buffer, creating it if necessary:
(with-current-buffer (decipher-stats-buffer t)
;; This can't happen, but it never hurts to double-check:
(or (eq major-mode 'decipher-stats-mode)
(error "Buffer %s is not in Decipher-Stats mode" (buffer-name)))
(setq buffer-read-only nil)
(erase-buffer)
;; Display frequency counts for letters A-Z:
(decipher-insert-frequency-counts freq-list total-chars)
(insert ?\n)
;; Display frequency counts for letters in order of frequency:
(setq freq-list (sort freq-list
(lambda (a b) (> (cl-second a) (cl-second b)))))
(decipher-insert-frequency-counts freq-list total-chars)
;; Display letters in order of frequency:
(insert ?\n (mapconcat (lambda (a) (char-to-string (car a)))
freq-list nil)
"\n\n")
;; Display list of digrams in order of frequency:
(let* ((rows (floor (+ (length decipher--digram-list) 9) 10))
(i rows)
temp-list)
(while (> i 0)
(setq temp-list decipher--digram-list)
(while temp-list
(insert (caar temp-list)
(format "%3d "
(cdar temp-list)))
(setq temp-list (nthcdr rows temp-list)))
(delete-horizontal-space)
(insert ?\n)
(setq decipher--digram-list (cdr decipher--digram-list)
i (1- i))))
;; Display adjacency list for each letter, sorted in descending
;; order of the number of adjacent letters:
(setq freq-list (sort freq-list
(lambda (a b) (> (cl-third a) (cl-third b)))))
(let ((temp-list freq-list)
entry i)
(while (setq entry (pop temp-list))
(if (equal 0 (cl-second entry))
nil ;This letter was not used
(setq i (- (car entry) ?A))
(insert ?\n " "
(decipher--digram-counts (aref decipher--before i)) ?\n
(car entry)
": A B C D E F G H I J K L M N O P Q R S T U V W X Y Z *"
(format "%4d %4d %3d%%\n "
(cl-third entry) (cl-second entry)
(floor (* 100.0 (cl-second entry)) total-chars))
(decipher--digram-counts (aref decipher--after i)) ?\n))))
(setq buffer-read-only t)
(set-buffer-modified-p nil)
))
(message nil))