нахождение частоты символов в общем лиспе - PullRequest
0 голосов
/ 05 ноября 2011

Например, если я ввожу последовательность символов

«Привет, мир» H = 1 e = 1 l = 3 o - 2 r = 1 w = 1 d = 1

можетпомогите мне

Я нашел этот код онлайн, но я не понимаю этого, я хочу более простой

(defun letter-freq (file)
 (with-open-file (stream file)
  (let ((str (make-string (file-length stream)))
        (arr (make-array 256 :element-type 'integer :initial-element 0)))
    (read-sequence str stream)
    (loop for c across str do (incf (aref arr (char-code c))))
    (loop for c from 32 to 126 for i from 1 do
      (format t "~c: ~d~a"
        (code-char c) (aref arr c)
        (if (zerop (rem i 8)) #\newline #\tab))))))

(letter-freq "test.lisp")

Ответы [ 4 ]

4 голосов
/ 05 ноября 2011

Приведенный выше код довольно специфичен для символов ASCII.Если вы хотите сделать то же самое для любого возможного символа, вы можете использовать хеш-таблицу. Директива формата

(defun letter-freq (file)
  (with-open-file (stream file)
    (let ((str (make-string (file-length stream)))
          (ht (make-hash-table)))
      (read-sequence str stream)
      (loop :for char :across str :do
        (incf (gethash char ht 0)))
      (maphash (lambda (k v)
                 (format t "~@C: ~D~%" k v))
               ht))))

~@C печатает символ, как если бы он был prin1.

2 голосов
/ 08 ноября 2011

Я бы разделил задачу на две меньшие задачи:

1 Чтение из файла и возврат строки 2 Подсчет частоты букв символов вstring

Для 1 вы можете использовать функцию file-string (https://github.com/kugelblitz/young/blob/master/external-helpers.lisp)

Для 2 , вы можете использовать 'bag'структура данных и библиотека пакетов fset (http://common -lisp.net / project / fset / ):

(defun letter-freq (str)
  (let ((bg (fset:convert 'fset:bag str)))
    (fset:do-bag-pairs (value mult bg)
                       (format t "~a: ~a~%" value mult))))
1 голос
/ 05 ноября 2011

Я бы склонен согласиться с Drysdam. Я некоторое время не касался кода Common Lisp и смог прочитать этот пример с общим пониманием, как он его описал.

Я не знаю, какую среду Lisp вы используете, но даже внутри голой CL REPL (чтение цикла печати eval) вы можете задать системе (describe 'some-unknown-symbol). И если вам случится быть «вынужденным» использовать Emacs, он имеет SLIME и множество функций.

Я вижу, это ваш второй вопрос, связанный с лиспом сегодня. Возможно, было бы лучше поразить какую-нибудь книгу с.

1 голос
/ 05 ноября 2011

Этот код не так сложен для понимания.Открывает файл, читает его в строку.Между тем, он также создает массив для хранения результатов (размер 256, потому что теоретически у вас могут быть непечатаемые символы выше 128, я думаю).Затем он перебирает массив и увеличивает соответствующий элемент в массиве.Например, 'a' равно 32, поэтому, когда он находит 'a', он увеличивает элемент массива 32.

В конце он перебирает только результаты печати и печатает их.

...