;; Peter Norvig - 从Erann Gat编程挑战:;; http://www.flownet.com/ron/papers/lisp-java/ ;;给出了一个单词列表和电话号码列表,查找所有方式;;每个电话号码都可以表示为单词列表。;; run :( main" word-list-file-name""电话号码文件名")(defvar * dict * nil"一个哈希表映射电话号码(整数)到输入字典的单词列表,从输入字典中产生该数字。")(裁员主要(& dict" dict" dict" nums" )(DICT-Size 100))"读取输入文件DICT并将其加载到* DICT *中。然后在NUM的每行,根据规则将数字的所有翻译成一系列单词,根据规则翻译。"(setf * dict *(load-dictionary dict dict-size))(有开放文件(在nums中)(num = num = nile的循环),而num do(打印 - 翻译num(删除 - if-not#39; digit-char-p num)))))(defun打印翻译(num digits&可选(start 0)(lock nil))"每种可能num的翻译成一串单词。数字必须是删除非数字的词。在递归调用上,开始是要查找下一个单词的数字的位置,而单词是单词f的位置for(subseq数字0开始)。因此,如果开始到达数字结束,那么我们有一个单词的解决方案。否则,对于数字的每个前缀,请在映射到前缀的值(逐渐计算为n)的字典中查看字典,并且对于每个这样的单词尝试使用递归调用扩展解决方案。有两个并发症:(1)规则说,除了字典单词,您还可以在输出中使用单个数字,但不是连续两位数字。此外(而这似乎是愚蠢的)你可以在可以出现任何单词的地方中有一个数字。我用找到的变量处理这个词;如果循环后是假的,并且最近的单词不是数字,请尝试按下数字的递归调用。 (2)其他并发症是将字符串映射到整数的明显方式将r到2和er到02映射到02,当然是2.因此我们将1送到每个数字,而且呃变成了102。" (如果(> = start(长度位数))(格式t"〜a:〜{〜a}〜%" num(verse word))(设:(fave-word nil)( n 1));领先的零问题(来自下面的开始(长度数字)执行(setf n(+(* 10n)(nth-位数i))))(gethash n * dict *循环(gethash n * dict * )DO(SETF找到-WORD T)(打印翻译NUM位数(+ 1 i)(缺点字词))))(当(和(不是找到-word)(notep(numberp)))))(打印翻译num位数(+开始1)(缺点(nth-digit开始)字))))))(defun load-dictionary(文件大小)"从单词文件中创建一个hashtable(每个线)。为初始散列大小提出提示。每个键都是单词的电话号码;每个值都是具有该电话号码的单词列表。"(bet(buck-hash-table:测试#' eql:size大小)))(用开放文件(文件)(word = word =(nil中的读取行),而word do(push word(gethash(word-> number word) )表)))))表))(defun字 - >数字(word)"翻译一个单词(字符串)根据规则,到电话号码。" ((n 1));领先的零问题(对于ch =(char字i)执行(何时(alpha-chel-p ch)(setf n(+(* 10)时) n)(char-> digit ch)))))))))(defun nth-digit(数字i)"数字字符串的第i个元素,作为整数0到9。& #34;( - (char-code(char数字i))#。(char-code#\ 0)))(defun char->数字(ch)"根据根据的数字将字符转换为数字电话号码规则。"(Ecase(Char-DownCase Ch)((#\ e)0)((#\ j#\ n#\ q \ 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 \ z)9)))