42 lines
1.2 KiB
Common Lisp
42 lines
1.2 KiB
Common Lisp
|
;;; anagram.lisp
|
||
|
;;; 2018-01-31
|
||
|
;;;
|
||
|
;;; Lisp implementation of this tweet:
|
||
|
;;; https://twitter.com/fermatslibrary/status/958700402647674880.
|
||
|
;;;
|
||
|
;;; Fun fact: this uses the prime list generated by
|
||
|
;;; (prime-numbers 26 3)
|
||
|
;;; using prime.rkt in the par/ toplevel directory. Why start at 3? It
|
||
|
;;; was a typo.
|
||
|
|
||
|
(defpackage #:anagram
|
||
|
(:use #:cl)
|
||
|
(:export #:anagram-p))
|
||
|
(in-package #:anagram)
|
||
|
|
||
|
(defun deconstruct (w)
|
||
|
"Convert a string into a list of characters (instead of an array of
|
||
|
characters)."
|
||
|
(loop for c across w collect c))
|
||
|
|
||
|
(defparameter *mapping*
|
||
|
(pairlis
|
||
|
(deconstruct "abcdefghijklmnopqrstuvwxyz")
|
||
|
'(3 5 7 11 13 17 19 23 29 31 37 41 43 47
|
||
|
53 59 61 67 71 73 79 83 89 97 101 103)))
|
||
|
|
||
|
(defun lookup (c)
|
||
|
"A hack to convert a character to its relevant prime."
|
||
|
(cdr (assoc c *mapping*)))
|
||
|
|
||
|
(defun word-number (word)
|
||
|
"Convert a word to a number by multiplying the associated prime
|
||
|
number for all the letters in the word."
|
||
|
(apply #'* (mapcar #'lookup
|
||
|
(deconstruct (string-downcase word)))))
|
||
|
|
||
|
(defun anagram-p (&rest words)
|
||
|
"Given a list of words, return T if they are all anagrams of each
|
||
|
other."
|
||
|
(apply #'= (mapcar #'word-number words)))
|