Concurrent Clean : send + more = money

http://d.hatena.ne.jp/syd_syd/20061018#p1
まずは、ナイーブに。

Start = [(s,e,n,d,m,o,r,y) \\
         s <- [1..9],
         e <- [0..9] | not (isMember e [s]),
         n <- [0..9] | not (isMember n [s,e]),
         d <- [0..9] | not (isMember d [s,e,n]),
         m <- [1..9] | not (isMember m [s,e,n,d]),
         o <- [0..9] | not (isMember o [s,e,n,d,m]),
         r <- [0..9] | not (isMember r [s,e,n,d,m,o]),
         y <- [0..9] | not (isMember y [s,e,n,d,m,o,r])
         && (s*1000+e*100+n*10+d) + (m*1000+o*100+r*10+e) == (m*10000+o*1000+n*100+e*10+y)]

順列を使って

perm :: [a] Int -> [[a]] | Eq a
perm _  0         = [[]]
perm ls i | i > 0 = [[a:ar] \\ a <- ls, ar <- perm (filter (\b = a <> b) ls) (dec i)]

Start = [(s,e,n,d,m,o,r,y) \\
         [s,e,n,d,m,o,r,y] <- perm [0..9] 8 |
         s <> 0 && m <> 0 &&
         (s*1000+e*100+n*10+d) + (m*1000+o*100+r*10+e) == (m*10000+o*1000+n*100+e*10+y)]

もうちょっと見やすく。

(base) infix 9
(base) ls b = base` 0 ls
  where
    base` n []     = n
    base` n [a:ar] = base` (n*b+a) ar

perm :: [a] Int -> [[a]] | Eq a
perm _  0         = [[]]
perm ls i | i > 0 = [[a:ar] \\ a <- ls, ar <- perm (filter (\b = a <> b) ls) (dec i)]

Start = [(s,e,n,d,m,o,r,y) \\
         [s,e,n,d,m,o,r,y] <- perm [0..9] 8 |
         s <> 0 && m <> 0 &&
         [s,e,n,d] base 10 + [m,o,r,e] base 10 == [m,o,n,e,y] base 10]

あ、ここはfoldlでいいのか