File: mpuz.sml

package info (click to toggle)
mlton 20100608-2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 34,980 kB
  • ctags: 69,089
  • sloc: ansic: 18,421; lisp: 2,879; makefile: 1,570; sh: 1,325; pascal: 256; asm: 97
file content (141 lines) | stat: -rw-r--r-- 3,826 bytes parent folder | download | duplicates (7)
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