Solution of Shady Fraiha
;; pairs = ( (letter1 digit1) (letter2 digit2) ... )
;; letters = ( alphabet of the problem )
;; lst = ( the three words of the problem )
(define (solve-alphametic lst)
(define w1 (every se (car lst)) ) ; separate letters of words
(define w2 (every se (cadr lst)) )
(define w3 (every se (caddr lst)) )
(define letters (remove-dup (se w1 w2 w3) ) ) ; domain of the problem
(if (> (count letters) 10) () ; 10 letters <--> 10 digits
; this is to save us the procesing of one more letter
(if (and (> (count w3) (count w2)) (> (count w3) (count w1)) )
; the left most letter of word3 is 1
(begin ; remove it from letters, and assign it 1
(define leters (remove (car w3) letters) )
(s-alpha (list (list (car w3) 1) ) leters lst)
)
;else
(s-alpha () letters lst)
)
)
)
(define (s-alpha pairs letters lst)
(cond ( (empty? letters) ; finished assigning values
(if (check pairs lst) ; values are correct
(qsort pairs) ; sort solution
; else ; not the correct values
() ) )
( #t (metic pairs letters 0 lst)) ;continue searching
)
)
(define (metic pairs letters dig lst)
(define fst (car letters) )
(define one (first (car lst ) ) ) ; first letter of first word
(define two (first (cadr lst) ) ) ; first letter of second word
(define tre (first (caddr lst) ) ) ; ...
(cond ((and (= dig 0)
(or (equal? fst one) (equal? fst two) (equal? fst tre)))
(metic pairs letters 1 lst)
) ; the first letter of a word cannot be 0
((= dig 10) () ) ; max digit is 9
( #t (if (conflict dig pairs) ; digit already used
(metic pairs letters (1+ dig) lst)
; else consider value as valid and continue
(let ((final
(s-alpha (cons (list fst dig) pairs)
(cdr letters) lst) ) )
(if final final
(metic pairs letters (1+ dig) lst))
)
)
)
)
)
(define (conflict n pairs) ; there is a conflict if the value is
; already used
(cond ((empty? pairs) #f)
((= (cadar pairs) n) #t)
(#t (conflict n (bf pairs) ) )
)
)
(define (check pairs lst)
(define num1 (transform pairs (car lst) )) ; get numbers out of words
(define num2 (transform pairs (cadr lst) ))
(define num3 (transform pairs (caddr lst) ))
(= (+ num1 num2) num3) ; check the summation
)
(define (transform pairs wd) ; change a word into a number using pairs
(cond ( (empty? wd) "")
(#t (word (trans pairs (first wd)) (transform pairs (bf wd) )))
)
)
(define (trans pairs lett) ; change a letter into a digit
(define par (assoc lett pairs) )
(cadr par)
)
(define (qsort l) ; to sort the final list of values (pairs)
(cond ((<= (count l) 1) l)
( (let ((pivot (caar l)))
(define les (keep (lambda (x) (before? (car x) pivot) ) l) )
(define mor (keep (lambda (x) (not (before? (car x) pivot)) )
(bf l)) )
(append (qsort les) (list (car l)) (qsort mor) )
)
)
)
)
(define (remove-dup l) ; rempve duplicates
(if (empty? l) l
(append (list (car l)) (remove-dup (remove (car l) l) ) )
)
)