;;; 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)))
