This code is intended to find all possible solutions to a cryptoarithmetic problem. The description of the problem I was trying to solve is here:
;;Cryptoarithmetic. In cryptoarithmetic problems, we are given a problem wherein the digits are replaced
;;with characters representing digits. A solution to such a problem is a set of digits that, when substituted
;;in the problem, gives a true numerical interpretation. Example:
;; IS
;; IT
;; ___
;; OK
;;
;; Has a solution { I = 1; K = 1; O = 3; S = 5; T = 6}. For each of the below cryptoarithmetic problems,
;; write a program that finds all the solutions in the shortest possible time.
;;
;; IS I
;; IT AM
;; __ __
;; OK OK
I was only able to solve it using brute force, though I believe there are more efficient methods. I am also hoping to receive feedback on my formatting, naming, and really anything you think could use improvement. If you have any comments on my code, I would be very grateful. Thanks for looking!
(defun place-value-to-integer (the-list &OPTIONAL place-value)
(let ((place-value (if place-value place-value 1)))
(if (= (length the-list) 1) (* place-value (first the-list))
(+ (* place-value (first (last the-list))) (place-value-to-integer (butlast the-list) (* 10 place-value))))))
(defun fill-from-formula (formula guess)
(loop for digit in formula collect (gethash digit guess)))
(defun check-answer (augend-formula addend-formula sum-formula guess)
(let ((augend (fill-from-formula augend-formula guess))
(addend (fill-from-formula addend-formula guess))
(sum (fill-from-formula sum-formula guess)))
(= (place-value-to-integer sum) (+ (place-value-to-integer augend) (place-value-to-integer addend)))))
(defun brute-force-guess(augend-formula addend-formula sum-formula unique-values &OPTIONAL callback guess)
(let ((guess (if (null guess) (make-hash-table) guess)))
(loop for digit in '(0 1 2 3 4 5 6 7 8 9) do
(setf (gethash (car unique-values) guess) digit)
(if (= (length unique-values) 1)
(if (check-answer augend-formula addend-formula sum-formula guess) (print-result augend-formula addend-formula sum-formula guess) nil)
(brute-force-guess augend-formula addend-formula sum-formula (cdr unique-values) callback guess)))))
(defun print-result (augend-formula addend-formula sum-formula guess)
(format t "One answer is ~a + ~a = ~a ~%"
(fill-from-formula augend-formula guess)
(fill-from-formula addend-formula guess)
(fill-from-formula sum-formula guess)))
(defun find-unique-values (the-list)
(let ((unique-items ()))
(loop for sublist in the-list do
(loop for item in sublist do
(unless (member item unique-items) (setf unique-items (append (list item) unique-items))))) unique-items))
(let ((problemA (list (list 'I 'S) (list 'I 'T) (list 'O 'K)))
(problemB (list (list 'I) (list 'A 'M) (list 'O 'K))))
(brute-force-guess (first problemA) (second problemA) (third problemA) (find-unique-values problemA) #'print-result)
(brute-force-guess (first problemB) (second problemB) (third problemB) (find-unique-values problemB) #'print-result))