Skip to content

Instantly share code, notes, and snippets.

@ebresafegaga
Last active November 11, 2020 20:01
Show Gist options
  • Save ebresafegaga/bdcde078c1dbf1e490d80a1d5fb44662 to your computer and use it in GitHub Desktop.
Save ebresafegaga/bdcde078c1dbf1e490d80a1d5fb44662 to your computer and use it in GitHub Desktop.
SEND + MORE = MONEY puzzle in F#
let rest = [0..9]
let first = [1..9]
type Letter = S | E | N | D | M | O | R | Y
let send = [S;E;N;D]
let more = [M;O;R;E]
let money = [M;O;N;E;Y]
let pick x letter =
match letter with
| S -> first
| M -> rems x first
| _ -> rems x rest
type Subst = Map<Letter, int>
let subst (map : Subst) xs =
List.foldBack (fun x s -> Map.find x map :: s) xs []
let (+.) x y =
let a = x + y
if a >= 10 then (a-10), (a/10)
else a, 0
let rec (|Snoc|Nil|) = function
| [] -> Nil
| x :: Nil -> Snoc (x, [])
| x :: Snoc (last, rest) -> Snoc (last, x :: rest)
let (++.) xs ys =
let rec loop carry result xs ys =
match xs, ys with
| Nil, Nil -> if carry=0 then result else (carry :: result)
| Nil, Snoc (y, ys) ->
let n, carry = 0 + y +. carry
loop carry (n :: result) xs ys
| Snoc (x, ys), Nil ->
let n, carry = x + 0 +. carry
loop carry (n :: result) xs ys
| Snoc (x, xs), Snoc (y, ys) ->
let n, carry = x + y +. carry
loop carry (n :: result) xs ys
loop 0 [] xs ys
let (~&) =
List.fold (fun s a -> s*10 + a) 0
let correct sub =
let subst' = subst sub
let s = subst' send // Send
let m = subst' more // More
let dols = subst' money // Money
let sum = s ++. m
&sum = &dols
let solve () : Subst list =
[ for s in pick [] S do
for m in pick [s] M do
for e in pick [s;m] E do
for n in pick [s;m;e] N do
for d in pick [s;m;e;n] D do
for o in pick [s;m;e;n;d] O do
for r in pick [s;m;e;n;d;o] R do
for y in pick [s;m;e;n;d;o;r] Y do
let sub = Map.ofList [(S,s); (E,e); (N,n); (D,d); (M,m); (O,o); (R,r); (Y,y)]
if correct sub then sub ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment