Thirteen Anagram

January 10, 2012

On December 7, 2011, Neil deGrasse Tyson tweeted:

Need a distraction today? Not only does 12+1=11+2, but the letters “twelve plus one” rearrange to give you “eleven plus two”

Mitchell Perilstein forwarded that tweet to me and suggested that it would form the basis of an exercise for Programming Praxis.

Your task is to write a program that finds equations similar to Tyson’s that form anagrams both in their symbols and in their letters. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

One Response to “Thirteen Anagram”

  1. mitchell perilstein said

    Here’s a little Emacs Lisp solution that handles the minimal case as posed. Minimal, because as you get larger, and use the operators more as in the moderator’s more general example, you’ll find more hits. As explorer, you will need to decide if you will accept negative subtraction results and nonzero division results. Does this work in any non-English languages?

    (defconst GENMAX 13)
    (defconst OPWORDS ‘((+ plus) (- minus) (* times) (/ divide)))
    (defconst NUMWORDS ‘(zero one two three four five six seven eight nine ten eleven twelve thirteen ))

    (defun math-words-equal (a b)
    (equal (sorted-explode (equation-to-mathwords a))
    (sorted-explode (equation-to-mathwords b))))

    (defun numword (n) (symbol-name (nth n NUMWORDS)))
    (defun opword (o) (symbol-name (cadr (assoc o OPWORDS))))
    (defun sorted-explode (str) (sort (coerce str ‘list) ‘<))

    (defun equation-to-mathwords (e)
    (concat (numword (cadr e)) " " (opword (car e)) " " (numword (caddr e))))

    (defun equations-equal (x y)
    (and (not (equal x y))
    (equal (eval x) (eval y))
    (math-words-equal x y)))

    (defun generate-equations () ;; ((- 5 5) (+ 5 5) (- 5 4) ….
    (let ((e nil)
    (ops (mapcar 'car OPWORDS)))
    (loop for i from 1 to GENMAX do
    (loop for j from 1 to i do
    (loop for op in ops do
    (if (not (and (equal op '-) (equal i j))) ;;; no 0's please
    (setq e (cons (list op i j) e))))))
    e))

    (defun thirteen ()
    (let ((all (generate-equations))
    (out nil))
    (loop for i from 1 to (length all) do
    (loop for j from 1 to i do
    (let ((a (nth i all))
    (b (nth j all)))
    (if (equations-equal a b)
    (setq out (cons (list
    a (equation-to-mathwords a)
    b (equation-to-mathwords b))
    out))))))
    out))

    ;; (thirteen)
    ;; (((+ 11 2) "eleven plus two" (+ 12 1) "twelve plus one"))

Leave a comment