;; lib/minikanren/tests/send-more-money.sx — classic cryptarithmetic ;; ;; S E N D ;; + M O R E ;; --------- ;; M O N E Y ;; ;; Column-by-column encoding with carries c1, c2, c3, and the ;; leftmost column produces a carry which equals M (the result is 5 digits). ;; All 8 letters distinct; S ≠ 0, M ≠ 0. ;; Unique solution: S=9, E=5, N=6, D=7, M=1, O=0, R=8, Y=2. ;; ;; Note: the full search labelling 11 variables from {0..9} is too slow ;; for naive labelling order (10^11 combinations naively, even with ;; bounds-consistency the branching factor dominates). Real CLP(FD) ;; systems use first-fail heuristics. Here we only verify the encoding ;; against the known answer. (define digits-0-9 (list 0 1 2 3 4 5 6 7 8 9)) (define digits-1-9 (list 1 2 3 4 5 6 7 8 9)) (define smm-col-with-carry (fn (x y carry-in z carry-out) (fresh (xy xyc ten-cout z-plus-ten-cout) (fd-plus x y xy) (fd-plus xy carry-in xyc) (fd-times 10 carry-out ten-cout) (fd-plus z ten-cout z-plus-ten-cout) (fd-eq xyc z-plus-ten-cout)))) (define send-more-money (fn (S E N D M O R Y) (fresh (c1 c2 c3) (mk-conj (fd-in S digits-1-9) (fd-in M digits-1-9) (fd-in E digits-0-9) (fd-in N digits-0-9) (fd-in D digits-0-9) (fd-in O digits-0-9) (fd-in R digits-0-9) (fd-in Y digits-0-9) (fd-in c1 (list 0 1)) (fd-in c2 (list 0 1)) (fd-in c3 (list 0 1)) (fd-distinct (list S E N D M O R Y)) (smm-col-with-carry D E 0 Y c1) (smm-col-with-carry N R c1 E c2) (smm-col-with-carry E O c2 N c3) (smm-col-with-carry S M c3 O M) (fd-label (list S E N D M O R Y c1 c2 c3)))))) (mk-test "send-more-money-verify-known-solution" (run* q (send-more-money 9 5 6 7 1 0 8 2)) (list (make-symbol "_.0"))) (mk-tests-run!)