1 package net.jankenpoi.sudokuki.solver;
\r
3 import net.jankenpoi.sudokuki.model.GridModel;
\r
5 public class BruteForceGridSolver implements GridSolver {
\r
7 private static final int MAX_ITER_NB = 20000;
\r
9 * Maybe spurious field - is it useful ??
\r
11 private final GridModel originalGrid;
\r
13 * Equivalent of 81 grids
\r
15 private final int[] cellShadowMemory = new int[81 * GRID_LENGTH];
\r
17 private int currentIndex = 0;
\r
19 private Boolean cancelled = Boolean.FALSE;
\r
21 public BruteForceGridSolver(GridModel originalGrid) {
\r
22 this.originalGrid = originalGrid;
\r
24 int[] originalFlags = originalGrid.cloneCellInfosAsInts();
\r
25 System.arraycopy(originalFlags, 0, cellShadowMemory, 0,
\r
26 originalFlags.length);
\r
29 private boolean cancelRequested() {
\r
30 synchronized (cancelled) {
\r
31 return cancelled.booleanValue();
\r
35 public void cancel() {
\r
36 synchronized (cancelled) {
\r
37 cancelled = Boolean.TRUE;
\r
42 public GridSolution resolve() {
\r
44 GridShadow gs = new GridShadow(cellShadowMemory, currentIndex, true); // 2.1
\r
46 boolean totalDeadEndNoSolution = false;
\r
48 for (int iter = 1; totalDeadEndNoSolution == false && iter < MAX_ITER_NB; iter++) {
\r
49 if (cancelRequested()) {
\r
53 int[] liCo = gs.popFirstCellWithMinPossValues(); // 3, 4
\r
57 if (li == 10 && co == 10) {
\r
61 * Return the solution
\r
63 short[] shorts = new short[GRID_LENGTH];
\r
64 for (int i=0; i<GRID_LENGTH; i++) {
\r
65 shorts[i] = (short) cellShadowMemory[currentIndex + i];
\r
67 GridModel solModel = new GridModel(shorts,
\r
69 GridSolution solution = new GridSolution(true, solModel);
\r
73 if (li == 11 && co == 11) {
\r
77 * Go back one position and continue the solving process
\r
79 totalDeadEndNoSolution = backToPreviousPosition();
\r
80 if (totalDeadEndNoSolution) {
\r
83 gs = new GridShadow(cellShadowMemory, currentIndex, false);
\r
88 byte value = gs.popFirstValueForCell(li, co); // 5
\r
90 copyCurrentFlagsToNextPosition(); // 6
\r
92 gs = new GridShadow(cellShadowMemory, currentIndex, false); // 7
\r
95 gs.setCellValueScreened(li, co, value); // 7
\r
97 forwardToNextPosition(); // 8
\r
98 gs = new GridShadow(cellShadowMemory, currentIndex, false); // 8
\r
101 boolean deadEnd = gs.setCellValueAt(li, co, value); // 8.1
\r
103 totalDeadEndNoSolution = backToPreviousPosition(); // 9
\r
104 gs = new GridShadow(cellShadowMemory, currentIndex, false); // 9.1
\r
110 GridSolution solution = new GridSolution(false, originalGrid);
\r
114 void copyCurrentFlagsToNextPosition() {
\r
115 if (currentIndex + GRID_LENGTH >= cellShadowMemory.length) {
\r
116 throw new IllegalStateException(
\r
117 "Already reached the end of the solver memory");
\r
119 System.arraycopy(cellShadowMemory, currentIndex, cellShadowMemory,
\r
120 currentIndex + GRID_LENGTH, GRID_LENGTH);
\r
123 void forwardToNextPosition() {
\r
124 currentIndex = currentIndex + GRID_LENGTH;
\r
127 boolean backToPreviousPosition() {
\r
128 currentIndex = currentIndex - GRID_LENGTH;
\r
129 if (currentIndex < 0) {
\r
138 int[] getCellShadowMemory() {
\r
139 return cellShadowMemory;
\r
145 int getCurrentIndex() {
\r
146 return currentIndex;
\r