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))