1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
(*
* Written by sweeks@sweeks.com on 1999-08-31.
*
* A solution to mpuz. (Try M-x mpuz in emacs.)
* This solution is very loosely based on an OCAML solution posted to
* comp.lang.ml by Laurent Vaucher <blo.b@infonie.fr>.
*)
(* override print so the benchmark is silent *)
fun print _ = ()
structure List =
struct
open List
fun exists(l, p) = List.exists p l
fun map(l, f) = List.map f l
fun fold(l, b, f) =
let
fun loop(l, b) =
case l of
[] => b
| x :: l => loop(l, f(x, b))
in loop(l, b)
end
fun foreach(l, f) = fold(l, (), fn (x, ()) => f x)
end
structure String =
struct
open String
fun fold(s, b, f) =
let
val n = size s
fun loop(i, b) =
if i = n
then b
else loop(i + 1, f(String.sub(s, i), b))
in loop(0, b)
end
end
structure Mpuz =
struct
fun solve(a, b, c, d, e) =
let
fun printNewline() = print "\n"
val sub = Array.sub
val update = Array.update
val letters =
List.fold
([a, b, c, d, e], [], fn (s, letters) =>
String.fold
(s, letters, fn (c, letters) =>
if List.exists(letters, fn c' => c = c')
then letters
else c :: letters))
val letterValues =
Array.array(Char.ord Char.maxChar + 1, 0)
fun letterValue(c) =
Array.sub(letterValues, ord c)
fun setLetterValue(c, v) =
Array.update(letterValues, ord c, v)
fun stringValue(s) =
String.fold(s, 0, fn (c, v) => v * 10 + letterValue c)
fun printResult() =
(List.foreach
(letters, fn c =>
print(concat[String.str(c), " = ",
Int.toString(letterValue(c)), " "]))
; print "\n")
fun testOk() =
let
val b0 = letterValue(String.sub(b, 1))
val b1 = letterValue(String.sub(b, 0))
val a = stringValue a
val b = stringValue b
val c = stringValue c
val d = stringValue d
val e = stringValue e
in if a * b0 = c
andalso a * b1 = d
andalso a * b = e
andalso c + d * 10 = e
then printResult()
else ()
end
val values = List.map([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], fn v =>
(v, ref false))
(* Try all assignments of values to letters. *)
fun loop(letters) =
case letters of
[] => testOk()
| c :: letters =>
List.foreach
(values, fn (v, r) =>
if !r
then ()
else (r := true
; setLetterValue(c, v)
; loop(letters)
; r := false))
in loop(letters)
end
end
structure Main =
struct
fun doit() =
Mpuz.solve("AGH", "FB", "CBEE", "GHFD", "FGIJE")
(*
* Solution:
* J = 0 I = 1 D = 8 E = 2 C = 5 B = 6 F = 4 H = 7 G = 3 A = 9
*)
val doit =
fn size =>
let
fun loop n =
if n = 0
then ()
else (doit();
loop(n-1))
in
loop size
end
end
|