Skip to content

Commit ecaa307

Browse files
author
renatoathaydes
committed
CL: use declaim optimize and sort functions
1 parent 6512a6f commit ecaa307

1 file changed

Lines changed: 38 additions & 37 deletions

File tree

src/lisp/main.lisp

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,30 @@
44
;; each phone number can be expressed as a list of words.
55
;; Run: (main "word-list-file-name" "phone-number-file-name")
66

7+
(declaim (optimize (speed 3) (debug 0) (safety 0)))
8+
79
(defglobal *dict* nil
810
"A hash table mapping a phone number (integer) to a list of words from the
911
input dictionary that produce that number.")
1012

13+
(defun nth-digit (digits i)
14+
"The i-th element of a character string of digits, as an integer 0 to 9."
15+
(- (char-code (char digits i)) #.(char-code #\0)))
16+
17+
(defun char->digit (ch)
18+
"Convert a character to a digit according to the phone number rules."
19+
(ecase (char-downcase ch)
20+
((#\e) 0)
21+
((#\j #\n #\q) 1)
22+
((#\r #\w #\x) 2)
23+
((#\d #\s #\y) 3)
24+
((#\f #\t) 4)
25+
((#\a #\m) 5)
26+
((#\c #\i #\v) 6)
27+
((#\b #\k #\u) 7)
28+
((#\l #\o #\p) 8)
29+
((#\g #\h #\z) 9)))
30+
1131
(defun choose-handler (print-or-count)
1232
"Chooses a solution handler function.
1333
When a numbers file is fully consumed, call the function with nil words to signal EOF."
@@ -24,18 +44,6 @@
2444
(format t "~a~%" count)
2545
(setf count 0)))))) ;; reset count for the next file
2646
(t (error "Unknown option: ~a" print-or-count))))
27-
28-
29-
(defun main (&optional print-or-count (dict "tests/words.txt") (nums "tests/numbers.txt") (dict-size 100))
30-
"Read the input file ¨DICT and load it into *dict*. Then for each line in
31-
NUMS, print all the translations of the number into a sequence of words,
32-
according to the rules of translation."
33-
(let ((handler (choose-handler print-or-count)))
34-
(setf *dict* (load-dictionary dict dict-size))
35-
(with-open-file (in nums)
36-
(loop for num = (read-line in nil) while num do
37-
(find-translations handler num (remove-if-not #'digit-char-p num))))
38-
(funcall handler "" nil)))
3947

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

79+
(defun word->number (word)
80+
"Translate a word (string) into a phone number, according to the rules."
81+
(let ((n 1)) ; leading zero problem
82+
(loop for i from 0 below (length word)
83+
for ch = (char word i) do
84+
(when (alpha-char-p ch) (setf n (+ (* 10 n) (char->digit ch)))))
85+
n))
86+
7187
(defun load-dictionary (file size)
7288
"Create a hashtable from the file of words (one per line). Takes a hint
7389
for the initial hashtable size. Each key is the phone number for a word;
@@ -78,30 +94,15 @@
7894
(push word (gethash (word->number word) table))))
7995
table))
8096

81-
(defun word->number (word)
82-
"Translate a word (string) into a phone number, according to the rules."
83-
(let ((n 1)) ; leading zero problem
84-
(loop for i from 0 below (length word)
85-
for ch = (char word i) do
86-
(when (alpha-char-p ch) (setf n (+ (* 10 n) (char->digit ch)))))
87-
n))
88-
89-
(defun nth-digit (digits i)
90-
"The i-th element of a character string of digits, as an integer 0 to 9."
91-
(- (char-code (char digits i)) #.(char-code #\0)))
92-
93-
(defun char->digit (ch)
94-
"Convert a character to a digit according to the phone number rules."
95-
(ecase (char-downcase ch)
96-
((#\e) 0)
97-
((#\j #\n #\q) 1)
98-
((#\r #\w #\x) 2)
99-
((#\d #\s #\y) 3)
100-
((#\f #\t) 4)
101-
((#\a #\m) 5)
102-
((#\c #\i #\v) 6)
103-
((#\b #\k #\u) 7)
104-
((#\l #\o #\p) 8)
105-
((#\g #\h #\z) 9)))
97+
(defun main (&optional print-or-count (dict "tests/words.txt") (nums "tests/numbers.txt") (dict-size 100))
98+
"Read the input file ¨DICT and load it into *dict*. Then for each line in
99+
NUMS, print all the translations of the number into a sequence of words,
100+
according to the rules of translation."
101+
(let ((handler (choose-handler print-or-count)))
102+
(setf *dict* (load-dictionary dict dict-size))
103+
(with-open-file (in nums)
104+
(loop for num = (read-line in nil) while num do
105+
(find-translations handler num (remove-if-not #'digit-char-p num))))
106+
(funcall handler "" nil)))
106107

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

0 commit comments

Comments
 (0)