-
Notifications
You must be signed in to change notification settings - Fork 0
/
dictionary.lisp
143 lines (122 loc) · 4.73 KB
/
dictionary.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
; Scrabble word dictionary
;
; Generally, words are lists of characters
;
; The dictionary is actually a dictionary of all word suffixes. That
; is, the word "busy" would include "busy", "usy", "sy" and "y". For
; each suffix, there is a "prefix dictionary", or pdictionary, of the
; prefix for that suffix, in reverse order.
;
; For example, a dictionary with the word "spot" and "rot" would
; include the suffix "ot", the dictionary node for 't' will have a
; terminal member that is itself a dictionary containing "sp" and "r".
;
; Because the dictionary contains all possible suffixes for a word,
; searching for a matching word through a square can include words
; that don't begin at that square. This makes finding legal plays
; much faster since we only have to consider legal play squares.
;
; The tradeoff is the upfront cost to build the dictionary and the
; memory required.
(defstruct dictionary
(terminal nil) ; If this is the end of a word,
; dictionary of prefixes. (or t if
; this is the prefix dictionary)
(letters nil)) ; alist of letter, dictionary
(defun dictionary-get-letter (dict letter)
"Return sub-dictionary associated with letter"
(let ((leaf (assoc (char-upcase letter) (dictionary-letters dict))))
(if leaf (cdr leaf) nil)))
(defun dictionary-get-leaf (dict word)
(dictionary-get-letter dict (car word)))
(defun dictionary-add-leaf (dict word)
(let ((leaf (dictionary-get-leaf dict word)))
(if (null leaf)
(progn
(setf leaf (make-dictionary))
(setf (dictionary-letters dict)
(acons (car word) leaf (dictionary-letters dict)))))
(values leaf)))
(defun dictionary-get-tail (dict word)
(cond
(word (dictionary-get-tail (dictionary-add-leaf dict word) (cdr word)))
(t dict)))
(defun dictionary-add (dict word)
(setf (dictionary-terminal (dictionary-get-tail dict word)) t))
(defun pdictionary-add-each (dict word rest)
(if word
(let ((tail (dictionary-get-tail dict word)))
(if (null (dictionary-terminal tail))
(setf (dictionary-terminal tail) (make-dictionary)))
(dictionary-add (dictionary-terminal tail) rest)
(pdictionary-add-each dict (cdr word) (cons (car word) rest)))))
(defun pdictionary-add (dict word)
(pdictionary-add-each dict word nil))
(defun dictionary-each-with (dict each thisword)
(if (dictionary-terminal dict)
(funcall each dict thisword))
(dolist (leaf (dictionary-letters dict))
(vector-push-extend (car leaf) thisword)
(dictionary-each-with (cdr leaf) each thisword)
(vector-pop thisword)))
(defun dictionary-each (dict each)
(dictionary-each-with dict
(function (lambda (leaf word)
(declare (ignore leaf))
(funcall each word)))
(make-fill-string)))
(defun pdictionary-prefix-each (dict suffix each)
(dictionary-each-with dict
(function (lambda (leaf prefix)
(declare (ignore leaf))
(funcall each (reverse prefix) suffix)))
(make-fill-string)))
(defun pdictionary-each (dict each)
(dictionary-each-with dict
(function (lambda (leaf suffix)
(pdictionary-prefix-each
(dictionary-terminal leaf) suffix each)))
(make-fill-string)))
(defun dictionary-dump (dict)
(dictionary-each dict (function (lambda (word) (write-line word)))))
(defun dictionary-update (dict file)
(with-open-file (in file)
(do ((line (read-line in nil)
(read-line in nil)))
((null line))
(dictionary-add dict (string-to-list line)))))
(defun pdictionary-update (dict file)
(with-open-file (in file)
(do ((line (read-line in nil)
(read-line in nil)))
((null line))
(pdictionary-add dict (string-to-list line)))))
(defun dictionary-lookup-prefix (dict word)
(cond
((null dict) nil)
((null word) dict)
(t (dictionary-lookup-prefix (dictionary-get-leaf dict word) (cdr word)))))
(defun dictionary-lookup (dict word)
(let ((leaf (dictionary-lookup-prefix dict word)))
(if (and leaf (dictionary-terminal leaf)) leaf nil)))
(defun load-dictionary (filename)
(let ((dict (make-dictionary)))
(dictionary-update dict filename)
(values dict)))
(defun load-pdictionary (filename)
(let ((dict (make-dictionary)))
(pdictionary-update dict filename)
(values dict)))
(defun lookup (argv)
(let ((dict (load-dictionary "./wordlist")))
(dolist (word (cdr argv))
(let ((leaf (dictionary-lookup-prefix dict (string-to-list word))))
(if leaf
(dictionary-each leaf (function (lambda (suffix) (format t "~A~A~%" word suffix)))))))))
(defun plookup (argv)
(let ((dict (make-dictionary)))
(pdictionary-update dict "./shortwords")
(dolist (word (cdr argv))
(let ((leaf (dictionary-lookup-prefix dict (string-to-list word))))
(if leaf
(pdictionary-each leaf (function (lambda (prefix suffix) (format t "~A~A~A~%" prefix word suffix)))))))))