OSDN Git Service

b5bd84a2cc047c49169fa2dde703a7c2d8e2ca95
[sudokuki/sudokuki.git] / src / classes / net / jankenpoi / sudokuki / generator / suexg / SuexgJava.java
1 /*\r
2  * Sudokuki - essential sudoku game\r
3  * Copyright (C) 2007-2013 Sylvain Vedrenne\r
4  *\r
5  * This program is free software: you can redistribute it and/or modify\r
6  * it under the terms of the GNU General Public License as published by\r
7  * the Free Software Foundation, either version 3 of the License, or\r
8  * (at your option) any later version.\r
9  *\r
10  * This program is distributed in the hope that it will be useful,\r
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13  * GNU General Public License for more details.\r
14  *\r
15  * You should have received a copy of the GNU General Public License\r
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
17  */\r
18 package net.jankenpoi.sudokuki.generator.suexg;\r
19 \r
20 import java.util.Random;\r
21 \r
22 import net.jankenpoi.sudokuki.SudokuGrid;\r
23 import net.jankenpoi.sudokuki.generator.SudokuGenerator;\r
24 \r
25 /*\r
26  *****************************************************************************\r
27  * This file results from Suexg's author initial work in the public domain   *\r
28  * and from Sudokuki's author.                                               *\r
29  *                                                                           *\r
30  * This is a GPLv3+ Java transposition of Suexg's original C source code.    *\r
31  * N.B: Instructions like 'goto label' are valid in C but not in Java,       *\r
32  * so I have transposed them using 'continue' inside a global while loop     *\r
33  * with boolean values and 'if' instructions to simulate the labels.         *\r
34  * And I replaced the B[] char table using the actual char values as int     *\r
35  *****************************************************************************\r
36  *  "Suexg version 12" is included in Sudokuki since version 0.0.12_gtkmm    *\r
37  *  of Sudokuki. The two reasons why I chose Suexg in the first place are    *\r
38  *  that it works and that it was public domain, so GPL compatible.          *\r
39  *  **************************************************************************\r
40  *  The note below (between * ... *) is from Suexg's author:                 *\r
41  *  **************************************************************************\r
42  *  * suexg version 12, small randomized sudoku-generator in C.            * *\r
43  *  *                                                                      * *\r
44  *  * Generates about 24 sudokus per second with 1GHz CPU.                 * *\r
45  *  * Based on an exact cover solver, compiled with gcc3.2. Report bugs,   * *\r
46  *  * improvement suggestions,feedback to sterten@aol.com. For some        * *\r
47  *  * explanation of the solver see: http://magictour.free.fr/suexco.txt   * *\r
48  *  * This generator starts from an empty grid and adds clues completely   * *\r
49  *  * at random. There are faster pseudo-random methods which generate     * *\r
50  *  * up to 1000 sudokus per second.    [..]                               * *\r
51  *  *                                                                      * *\r
52  *  * Send sudokus with rating more than 100000 to sterten@aol.com so they * *\r
53  *  * can be included in the list of hardest sudokus at                    * *\r
54  *  * http://magictour.free.fr/top94    [..]                               * *\r
55  *  *                                                                      * *\r
56  *****************************************************************************\r
57  */\r
58 class SuexgJava extends SuexgGenerator {\r
59 \r
60         private static long zr = 362436069;\r
61         private static long wr = 521288629;\r
62         private final static int[] A = new int[88];\r
63         private final static int[] C = new int[88];\r
64         private final static int[] I = new int[88];\r
65         private final static int[] P = new int[88];\r
66         private final static int[] V = new int[325];\r
67         private final static int[] W = new int[325];\r
68         private final static int[][] Col = new int[730][5];\r
69         private final static int[][] Row = new int[325][10];\r
70         private final static int[] Cols = new int[730];\r
71         private final static int[] Rows = new int[325];\r
72         private final static int[] Uc = new int[325];\r
73         private final static int[] Ur = new int[730];\r
74         private final static int[] Two = new int[888];\r
75 \r
76         private static int a;\r
77         private static int c;\r
78         private static int d;\r
79         private static int f;\r
80         private static int i;\r
81         private static int j;\r
82         private static int k;\r
83         private static int l;\r
84         private static int r;\r
85         private static int n = 729;\r
86         private static int m = 324;\r
87         private static int s;\r
88         private static int w;\r
89         private static int x;\r
90         private static int y;\r
91 \r
92         private static int c1;\r
93         private static int c2;\r
94         private static int i1;\r
95         private static int m0;\r
96         private static int m1;\r
97         private static int m2;\r
98         private static int r1;\r
99         private static int s1;\r
100 \r
101         private static int clues;\r
102         private static int min;\r
103         private static int nodes;\r
104         private static int nt;\r
105         private static int rate;\r
106         private static int sam1;\r
107         private static int samples;\r
108         // private static int seed;\r
109         private static int solutions;\r
110         private final static int[] B = new int[] { 48, 49, 49, 49, 50, 50, 50, 51,\r
111                         51, 51, 49, 49, 49, 50, 50, 50, 51, 51, 51, 49, 49, 49, 50, 50, 50,\r
112                         51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 52, 52, 52, 53, 53,\r
113                         53, 54, 54, 54, 52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56,\r
114                         56, 56, 57, 57, 57, 55, 55, 55, 56, 56, 56, 57, 57, 57, 55, 55, 55,\r
115                         56, 56, 56, 57, 57, 57 };\r
116 \r
117         private static int MWC() {\r
118                 final int result;\r
119                 zr = 36969 * (zr & 65535) + (zr >> 16);\r
120                 wr = 18000 * (wr & 65535) + (wr >> 16);\r
121                 result = (int) (zr ^ wr);\r
122                 return result;\r
123         }\r
124 \r
125         @Override\r
126         public synchronized SudokuGrid generateGrid(final int requestedRatingMin, final int requestedRatingMax) {\r
127                 Random rand = new Random(System.currentTimeMillis());\r
128 \r
129                 int[] grid = new int[81];\r
130                 int[] gridAndClues = new int[81];\r
131                 int[] rating = new int[] { -1 };\r
132                 int seed = rand.nextInt();\r
133                 gridGenerate(seed, requestedRatingMin, requestedRatingMax, grid, rating, gridAndClues);\r
134                 //printGrid(grid);\r
135                 //printGrid(gridAndClues);\r
136 \r
137                 SudokuGrid sudoku = new SudokuGrid(grid);\r
138                 return sudoku;\r
139         }\r
140 \r
141 \r
142         private int\r
143         gridGenerate(final int seed, final int requestedRatingMin, final int requestedRatingMax, final int[] grid, final int[] rating,\r
144                         final int[] grid_with_clues) {\r
145 \r
146                 /*\r
147                  * boolean values used to simulate the infamous goto used in the\r
148                  * original C suexg algorithm\r
149                  */\r
150                 boolean gotoM0S = true;\r
151                 boolean gotoMR1 = false, gotoMR3 = false, gotoM0 = false;\r
152 \r
153                 zr ^= seed;\r
154                 wr += seed;\r
155 \r
156                 samples = 1; // number of grids to generate (here only one grid is\r
157                                                 // generated)\r
158                 rate = 1; // if this value is not zero, the program will calculate the\r
159                                         // rating (for each grid)\r
160 \r
161                 for (i = 0; i < 888; i++) {\r
162                         j = 1;\r
163                         while (j <= i) {\r
164                                 j += j;\r
165                         }\r
166                         Two[i] = j - 1;\r
167                 }\r
168 \r
169                 r = 0;\r
170                 for (x = 1; x <= 9; x++) {\r
171                         for (y = 1; y <= 9; y++) {\r
172                                 for (s = 1; s <= 9; s++) {\r
173                                         r++;\r
174                                         Cols[r] = 4;\r
175                                         Col[r][1] = x * 9 - 9 + y;\r
176                                         Col[r][2] = (B[x * 9 - 9 + y] - 48) * 9 - 9 + s + 81;\r
177                                         Col[r][3] = x * 9 - 9 + s + 81 * 2;\r
178                                         Col[r][4] = y * 9 - 9 + s + 81 * 3;\r
179                                 }\r
180                         }\r
181                 }\r
182                 for (c = 1; c <= m; c++) {\r
183                         Rows[c] = 0;\r
184                 }\r
185                 for (r = 1; r <= n; r++) {\r
186                         for (c = 1; c <= Cols[r]; c++) {\r
187                                 a = Col[r][c];\r
188                                 Rows[a]++;\r
189                                 Row[a][Rows[a]] = r;\r
190                         }\r
191                 }\r
192 \r
193                 sam1 = 0;\r
194 \r
195                 while (true) {\r
196                         // m0s:\r
197                         if (gotoM0S) {\r
198                                 gotoM0S = false;\r
199                                 sam1++;\r
200                                 if (sam1 > samples) {\r
201                                         return 0;\r
202                                 } else {\r
203                                         gotoM0 = true;\r
204                                 }\r
205                         } // end of MOS if\r
206 \r
207                         // m0:\r
208                         if (gotoM0) {\r
209                                 gotoM0 = false;\r
210                                 for (i = 1; i <= 81; i++) {\r
211                                         A[i] = 0;\r
212                                 }\r
213                                 gotoMR1 = true;\r
214                         } // end of M0 if\r
215 \r
216                         // mr1:\r
217                         if (gotoMR1) {\r
218                                 gotoMR1 = false;\r
219                                 i1 = (MWC() >> 8) & 127;\r
220                                 if (i1 > 80) {\r
221                                         gotoMR1 = true;\r
222                                         continue; // these 2 instructions stand for: goto mr1;\r
223                                 }\r
224                                 i1++;\r
225                                 if (A[i1] != 0) {\r
226                                         gotoMR1 = true;\r
227                                         continue; // these 2 instructions stand for: goto mr1;\r
228                                 }\r
229                                 gotoMR3 = true;\r
230                         }\r
231 \r
232                         // mr3:\r
233                         if (gotoMR3) {\r
234                                 gotoMR3 = false;\r
235                                 s = (MWC() >> 9) & 15;\r
236                                 if (s > 8) {\r
237                                         gotoMR3 = true;\r
238                                         continue; // these 2 instructions stand for: goto mr3;\r
239                                 }\r
240                                 s++;\r
241                                 A[i1] = s;\r
242                                 m2 = solve();\r
243 \r
244                                 // add a random clue and solve it. No solution ==> remove it\r
245                                 // again.\r
246                                 // Not yet a unique solution ==> continue adding clues\r
247                                 if (m2 < 1) {\r
248                                         A[i1] = 0;\r
249                                 }\r
250                                 if (m2 != 1) {\r
251                                         gotoMR1 = true;\r
252                                         continue; // these 2 instructions stand for: goto mr1;\r
253                                 }\r
254 \r
255                                 if (solve() != 1) {\r
256                                         gotoM0 = true;\r
257                                         continue; // these 2 instructions stand for: goto m0;\r
258                                 }\r
259                                 // now we have a unique-solution sudoku. Now remove clues to\r
260                                 // make it minimal\r
261                                 {// EXPERIMENTAL: here is the grid with clues in it\r
262                                         for (i = 1; i <= 81; i++) {\r
263                                                 grid_with_clues[i - 1] = A[i];\r
264                                         }\r
265                                 }\r
266                                 for (i = 1; i <= 81; i++) {\r
267 \r
268                                         x = i;\r
269                                         while (x >= i) {\r
270                                                 // mr4:\r
271                                                 x = (MWC() >> 8) & 127;\r
272                                         }\r
273                                         x++;\r
274                                         P[i] = P[x];\r
275                                         P[x] = i;\r
276                                 }\r
277                                 for (i1 = 1; i1 <= 81; i1++) {\r
278                                         s1 = A[P[i1]];\r
279                                         A[P[i1]] = 0;\r
280                                         if (solve() > 1) {\r
281                                                 A[P[i1]] = s1;\r
282                                         }\r
283                                 }\r
284 \r
285                                 if (rate != 0) {\r
286                                         nt = 0;\r
287                                         for (f = 0; f < 100; f++) {\r
288                                                 solve();\r
289                                                 nt += nodes;\r
290                                         }\r
291                                         \r
292                                         if (nt < requestedRatingMin|| requestedRatingMax < nt) {\r
293                                                 gotoM0 = true;\r
294                                                 continue;\r
295                                         }\r
296                                         rating[0] = nt;\r
297                                 }\r
298 \r
299                                 {\r
300 \r
301                                         for (i = 1; i <= 81; i++) {\r
302                                                 grid[i - 1] = A[i];\r
303                                         }\r
304                                 }\r
305                                 gotoM0S = true;\r
306                                 continue; // these 2 instructions stand for: goto m0s;\r
307                         } // end of gotoMR3 if\r
308 \r
309                 } // outer while loop\r
310         }\r
311 \r
312         // -----------------------------------------------------------------------\r
313         // -----------------------------------------------------------------------\r
314 \r
315         private static int solve() {// returns 0 (no solution), 1 (unique sol.), 2\r
316                                                                 // (more\r
317                 // than one sol.)\r
318 \r
319                 /*\r
320                  * boolean values used to simulate the infamous goto used in the\r
321                  * original C suexg algorithm\r
322                  */\r
323                 boolean gotoM2 = true, gotoM3 = false, gotoM4 = false, gotoMR = false;\r
324 \r
325                 for (i = 0; i <= n; i++) {\r
326                         Ur[i] = 0;\r
327                 }\r
328                 for (i = 0; i <= m; i++) {\r
329                         Uc[i] = 0;\r
330                 }\r
331                 clues = 0;\r
332                 for (i = 1; i <= 81; i++) {\r
333                         if (A[i] != 0) {\r
334                                 clues++;\r
335                                 r = i * 9 - 9 + A[i];\r
336                                 for (j = 1; j <= Cols[r]; j++) {\r
337                                         d = Col[r][j];\r
338                                         if (Uc[d] != 0) {\r
339                                                 return 0;\r
340                                         }\r
341                                         Uc[d]++;\r
342                                         for (k = 1; k <= Rows[d]; k++) {\r
343                                                 Ur[Row[d][k]]++;\r
344                                         }\r
345                                 }\r
346                         }\r
347                 }\r
348 \r
349                 for (c = 1; c <= m; c++) {\r
350                         V[c] = 0;\r
351                         for (r = 1; r <= Rows[c]; r++) {\r
352                                 if (Ur[Row[c][r]] == 0) {\r
353                                         V[c]++;\r
354                                 }\r
355                         }\r
356                 }\r
357 \r
358                 i = clues;\r
359                 m0 = 0;\r
360                 m1 = 0;\r
361                 solutions = 0;\r
362                 nodes = 0;\r
363 \r
364                 whileloop: while (true) {\r
365 \r
366                         // m2: //////////\r
367                         if (gotoM2) {\r
368                                 gotoM2 = false;\r
369 \r
370                                 i++;\r
371                                 I[i] = 0;\r
372                                 min = n + 1;\r
373 \r
374                                 if (i > 81 || m0 != 0) {\r
375                                         gotoM4 = true;\r
376                                         continue; // simulates: goto m4;\r
377                                 }\r
378                                 if (m1 != 0) {\r
379                                         C[i] = m1;\r
380                                         gotoM3 = true;\r
381                                         continue; // simulates: goto m3;\r
382                                 }\r
383 \r
384                                 w = 0;\r
385                                 for (c = 1; c <= m; c++) {\r
386                                         if (Uc[c] == 0) {\r
387                                                 if (V[c] < 2) {\r
388                                                         C[i] = c;\r
389                                                         gotoM3 = true;\r
390                                                         continue whileloop; // simulates: goto m3;\r
391                                                 }\r
392                                                 if (V[c] <= min) {\r
393                                                         w++;\r
394                                                         W[w] = c;\r
395                                                 }\r
396                                                 \r
397                                                 if (V[c] < min) {\r
398                                                         w = 1;\r
399                                                         W[w] = c;\r
400                                                         min = V[c];\r
401                                                 }\r
402                                         }\r
403                                 }\r
404                                 gotoMR = true;\r
405                         }\r
406 \r
407                         // /mr:\r
408                         if (gotoMR) {\r
409                                 gotoMR = false;\r
410 \r
411                                 c2 = (MWC() & Two[w]);\r
412                                 if (c2 >= w) {\r
413                                         gotoMR = true;\r
414                                         continue; // simulates: goto mr;\r
415                                 }\r
416                                 C[i] = W[c2 + 1];\r
417                                 gotoM3 = true;\r
418                         }\r
419 \r
420                         // m3: //////\r
421                         if (gotoM3) {\r
422                                 gotoM3 = false;\r
423 \r
424                                 c = C[i];\r
425                                 I[i]++;\r
426                                 if (I[i] > Rows[c]) {\r
427                                         gotoM4 = true;\r
428                                         continue; // simulates: goto m4;\r
429                                 }\r
430                                 r = Row[c][I[i]];\r
431                                 if (Ur[r] != 0) {\r
432                                         gotoM3 = true;\r
433                                         continue; // simulates: goto m3;\r
434                                 }\r
435                                 m0 = 0;\r
436                                 m1 = 0;\r
437                                 nodes++;// if(nodes>9999 && part==0)return 0;\r
438                                 for (j = 1; j <= Cols[r]; j++) {\r
439                                         c1 = Col[r][j];\r
440                                         Uc[c1]++;\r
441                                 }\r
442                                 for (j = 1; j <= Cols[r]; j++) {\r
443                                         c1 = Col[r][j];\r
444                                         for (k = 1; k <= Rows[c1]; k++) {\r
445                                                 r1 = Row[c1][k];\r
446                                                 Ur[r1]++;\r
447                                                 if (Ur[r1] == 1) {\r
448                                                         for (l = 1; l <= Cols[r1]; l++) {\r
449                                                                 c2 = Col[r1][l];\r
450                                                                 V[c2]--;\r
451                                                                 if (Uc[c2] + V[c2] < 1) {\r
452                                                                         m0 = c2;\r
453                                                                 }\r
454                                                                 if (Uc[c2] == 0 && V[c2] < 2) {\r
455                                                                         m1 = c2;\r
456                                                                 }\r
457                                                         }\r
458                                                 }\r
459                                         }\r
460                                 }\r
461                                 if (i == 81) {\r
462                                         solutions++;\r
463                                 }\r
464                                 if (solutions > 1) {\r
465                                         break; // simulates: goto m9;\r
466                                 }\r
467                                 gotoM2 = true;\r
468                                 continue; // simulates: goto m2;\r
469                         } // end of m3 if\r
470 \r
471                         // m4: ////\r
472                         if (gotoM4) {\r
473                                 gotoM4 = false;\r
474 \r
475                                 i--;\r
476                                 c = C[i];\r
477                                 r = Row[c][I[i]];\r
478                                 if (i == clues) {\r
479                                         break; // simulates: goto m9;\r
480                                 }\r
481                                 for (j = 1; j <= Cols[r]; j++) {\r
482                                         c1 = Col[r][j];\r
483                                         Uc[c1]--;\r
484                                         for (k = 1; k <= Rows[c1]; k++) {\r
485                                                 r1 = Row[c1][k];\r
486                                                 Ur[r1]--;\r
487                                                 if (Ur[r1] == 0) {\r
488                                                         for (l = 1; l <= Cols[r1]; l++) {\r
489                                                                 c2 = Col[r1][l];\r
490                                                                 V[c2]++;\r
491                                                         }\r
492                                                 }\r
493                                         }\r
494                                 }\r
495 \r
496                                 if (i > clues) {\r
497                                         gotoM3 = true;\r
498                                         continue; // simulates: goto m3;\r
499                                 }\r
500                         } // end of m4 if\r
501 \r
502                         break;\r
503                 } // outer while loop\r
504 \r
505                 // m9: /////\r
506                 return solutions;\r
507         }\r
508 \r
509         private static final SuexgJava INSTANCE;\r
510         static {\r
511                 INSTANCE = new SuexgJava();\r
512         }\r
513         \r
514         public static SudokuGenerator getGenerator() {\r
515                 return INSTANCE;\r
516         }\r
517 \r
518 }