Skip to content

Commit

Permalink
CL: use declaim optimize and sort functions
Browse files Browse the repository at this point in the history
  • Loading branch information
renatoathaydes committed Oct 3, 2021
1 parent 6512a6f commit ecaa307
Showing 1 changed file with 38 additions and 37 deletions.
75 changes: 38 additions & 37 deletions src/lisp/main.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,30 @@
;; each phone number can be expressed as a list of words.
;; Run: (main "word-list-file-name" "phone-number-file-name")

(declaim (optimize (speed 3) (debug 0) (safety 0)))

(defglobal *dict* nil
"A hash table mapping a phone number (integer) to a list of words from the
input dictionary that produce that number.")

(defun nth-digit (digits i)
"The i-th element of a character string of digits, as an integer 0 to 9."
(- (char-code (char digits i)) #.(char-code #\0)))

(defun char->digit (ch)
"Convert a character to a digit according to the phone number rules."
(ecase (char-downcase ch)
((#\e) 0)
((#\j #\n #\q) 1)
((#\r #\w #\x) 2)
((#\d #\s #\y) 3)
((#\f #\t) 4)
((#\a #\m) 5)
((#\c #\i #\v) 6)
((#\b #\k #\u) 7)
((#\l #\o #\p) 8)
((#\g #\h #\z) 9)))

(defun choose-handler (print-or-count)
"Chooses a solution handler function.
When a numbers file is fully consumed, call the function with nil words to signal EOF."
Expand All @@ -24,18 +44,6 @@
(format t "~a~%" count)
(setf count 0)))))) ;; reset count for the next file
(t (error "Unknown option: ~a" print-or-count))))


(defun main (&optional print-or-count (dict "tests/words.txt") (nums "tests/numbers.txt") (dict-size 100))
"Read the input file ¨DICT and load it into *dict*. Then for each line in
NUMS, print all the translations of the number into a sequence of words,
according to the rules of translation."
(let ((handler (choose-handler print-or-count)))
(setf *dict* (load-dictionary dict dict-size))
(with-open-file (in nums)
(loop for num = (read-line in nil) while num do
(find-translations handler num (remove-if-not #'digit-char-p num))))
(funcall handler "" nil)))

(defun find-translations (handler num digits &optional (start 0) (words nil))
"Print each possible translation of NUM into a string of words. DIGITS
Expand Down Expand Up @@ -68,6 +76,14 @@
(find-translations handler num digits (+ start 1)
(cons (nth-digit digits start) words))))))

(defun word->number (word)
"Translate a word (string) into a phone number, according to the rules."
(let ((n 1)) ; leading zero problem
(loop for i from 0 below (length word)
for ch = (char word i) do
(when (alpha-char-p ch) (setf n (+ (* 10 n) (char->digit ch)))))
n))

(defun load-dictionary (file size)
"Create a hashtable from the file of words (one per line). Takes a hint
for the initial hashtable size. Each key is the phone number for a word;
Expand All @@ -78,30 +94,15 @@
(push word (gethash (word->number word) table))))
table))

(defun word->number (word)
"Translate a word (string) into a phone number, according to the rules."
(let ((n 1)) ; leading zero problem
(loop for i from 0 below (length word)
for ch = (char word i) do
(when (alpha-char-p ch) (setf n (+ (* 10 n) (char->digit ch)))))
n))

(defun nth-digit (digits i)
"The i-th element of a character string of digits, as an integer 0 to 9."
(- (char-code (char digits i)) #.(char-code #\0)))

(defun char->digit (ch)
"Convert a character to a digit according to the phone number rules."
(ecase (char-downcase ch)
((#\e) 0)
((#\j #\n #\q) 1)
((#\r #\w #\x) 2)
((#\d #\s #\y) 3)
((#\f #\t) 4)
((#\a #\m) 5)
((#\c #\i #\v) 6)
((#\b #\k #\u) 7)
((#\l #\o #\p) 8)
((#\g #\h #\z) 9)))
(defun main (&optional print-or-count (dict "tests/words.txt") (nums "tests/numbers.txt") (dict-size 100))
"Read the input file ¨DICT and load it into *dict*. Then for each line in
NUMS, print all the translations of the number into a sequence of words,
according to the rules of translation."
(let ((handler (choose-handler print-or-count)))
(setf *dict* (load-dictionary dict dict-size))
(with-open-file (in nums)
(loop for num = (read-line in nil) while num do
(find-translations handler num (remove-if-not #'digit-char-p num))))
(funcall handler "" nil)))

(apply #'main (cdr sb-ext:*posix-argv*))

0 comments on commit ecaa307

Please sign in to comment.