word_freq.lisp en Lisp
Cuenta la frecuencia de las palabras de un pasaje incluido e imprime una tabla ordenada.
;; word_freq.lisp: word frequency report over an inline passage.
(defparameter *passage*
"The quick brown fox jumps over the lazy dog. The dog barks
and the fox runs. Quick thinking saved the fox that day.")
(defun word-char-p (ch)
(or (alpha-char-p ch) (char= ch #\')))
(defun split-words (text)
"Return TEXT as a list of lowercase words with punctuation dropped."
(let ((words '())
(start nil))
(dotimes (i (length text))
(let ((ch (char text i)))
(cond ((and (word-char-p ch) (null start))
(setf start i))
((and (not (word-char-p ch)) start)
(push (string-downcase (subseq text start i)) words)
(setf start nil)))))
(when start
(push (string-downcase (subseq text start)) words))
(nreverse words)))
(defun tally (words)
"Return (word . count) pairs, most frequent first, ties alphabetical."
(let ((counts (make-hash-table :test #'equal))
(pairs '()))
(dolist (word words)
(incf (gethash word counts 0)))
(maphash (lambda (word count) (push (cons word count) pairs)) counts)
(sort pairs (lambda (a b)
(if (= (cdr a) (cdr b))
(string< (car a) (car b))
(> (cdr a) (cdr b)))))))
(let* ((words (split-words *passage*))
(ranked (tally words))
(singles (remove-if-not (lambda (pair) (= (cdr pair) 1)) ranked)))
(format t "~d words, ~d unique~%~%" (length words) (length ranked))
(format t "~12a ~5a~%" "word" "count")
(dolist (pair (subseq ranked 0 (min 6 (length ranked))))
(format t "~12a ~5d~%" (car pair) (cdr pair)))
(format t "~%~d word~:p appeared exactly once~%" (length singles)))
Cómo funciona
split-wordsrecorre el texto carácter por carácter y corta palabras dondeword-char-prechaza.tallycuenta en una tabla hash creada con:test #'equal, y luegomaphashjunta pares parasort.- Los empates se rompen alfabéticamente con
string<, y~12a ~5dalinea las filas impresas.
Palabras clave y builtins usados aquí
andcarcdrcharcondconscountdefparameterdefundolistdotimesequalformatgethashifincflambdalengthletmaphashminnotnreversenullorpushsetfsortsubseqwhen
El intento, en números
- Líneas
- 44
- Caracteres a escribir
- 1490
- Tokens
- 356
- Ritmo de tres estrellas
- 75 tpm
Al ritmo de tres estrellas de 75 tokens por minuto, este intento toma unos 285 segundos.
Paso 1 de 3 en Bis; paso 25 de 27 en Fundamentos del lenguaje.