src/de/uapcore/sudoku/Solver.java

changeset 7
2c0a2766461c
parent 5
8ddf4af937d7
child 8
e70a0e3555fb
     1.1 --- a/src/de/uapcore/sudoku/Solver.java	Sun Jan 27 15:03:57 2013 +0100
     1.2 +++ b/src/de/uapcore/sudoku/Solver.java	Thu Jan 31 18:44:44 2013 +0100
     1.3 @@ -26,6 +26,9 @@
     1.4  
     1.5  package de.uapcore.sudoku;
     1.6  
     1.7 +import java.util.ArrayList;
     1.8 +import java.util.List;
     1.9 +
    1.10  /**
    1.11   *
    1.12   * @author mike
    1.13 @@ -35,6 +38,144 @@
    1.14      public Solver() {
    1.15      }
    1.16      
    1.17 +    private Integer fillInCandidate(Field f, List<Integer>[][] candidates, int x, int y) {
    1.18 +        Integer c = candidates[x][y].remove(0);
    1.19 +        f.setCellValue(x, y, c);
    1.20 +        f.setCellModified(x, y, true);
    1.21 +        for (int i = 0 ; i < 9 ; i++) {
    1.22 +            candidates[x][i].remove(c);
    1.23 +            candidates[i][y].remove(c);
    1.24 +        }
    1.25 +        for (int i = 0 ; i < 3 ; i++) {
    1.26 +            for (int j = 0 ; j < 3 ; j++) {
    1.27 +                candidates[x-x%3+i][y-y%3+j].remove(c);
    1.28 +            }
    1.29 +        }
    1.30 +        return c;
    1.31 +    }
    1.32 +    
    1.33 +    private void makeBackup(List<Integer>[][] candidates, List<Integer>[][] candidatesBackup) {
    1.34 +        for (int x = 0 ; x < 9 ; x++) {
    1.35 +            for (int y = 0 ; y < 9 ; y++) {
    1.36 +                candidatesBackup[x][y] = new ArrayList<>(9);
    1.37 +                candidatesBackup[x][y].addAll(candidates[x][y]);
    1.38 +            }
    1.39 +        }
    1.40 +    }
    1.41 +    
    1.42 +    private void makeBackup(Field f, int[][] fieldBackup) {
    1.43 +        for (int x = 0 ; x < 9 ; x++) {
    1.44 +            for (int y = 0 ; y < 9 ; y++) {
    1.45 +                fieldBackup[x][y] = f.getCellValue(x, y);
    1.46 +            }
    1.47 +        }
    1.48 +    }
    1.49 +    
    1.50 +    private void restoreBackup(Field f, int[][] fieldBackup) {
    1.51 +        for (int x = 0 ; x < 9 ; x++) {
    1.52 +            for (int y = 0 ; y < 9 ; y++) {
    1.53 +                f.setCellValue(x, y, fieldBackup[x][y]);
    1.54 +            }
    1.55 +        }
    1.56 +    }
    1.57 +    
    1.58 +    private void restoreBackup(List<Integer>[][] candidates, List<Integer>[][] candidatesBackup) {
    1.59 +        for (int x = 0 ; x < 9 ; x++) {
    1.60 +            for (int y = 0 ; y < 9 ; y++) {
    1.61 +                candidates[x][y].clear();
    1.62 +                candidates[x][y].addAll(candidatesBackup[x][y]);
    1.63 +            }
    1.64 +        }
    1.65 +    }
    1.66 +    
    1.67 +    private boolean solve(Field f, List<Integer>[][] candidates) {
    1.68 +        
    1.69 +        // Make backup
    1.70 +        List<Integer>[][] candidatesBackup = new List[9][9];
    1.71 +        int[][] fieldBackup = new int[9][9];
    1.72 +        makeBackup(candidates, candidatesBackup);
    1.73 +        makeBackup(f, fieldBackup);
    1.74 +        
    1.75 +        // Fill in distinct solutions
    1.76 +        boolean fillDistinct;
    1.77 +        do {
    1.78 +            fillDistinct = false;
    1.79 +            for (int x = 0 ; x < 9 ; x++) {
    1.80 +                for (int y = 0 ; y < 9 ; y++) {
    1.81 +                    if (f.isCellEmpty(x, y) && candidates[x][y].size() == 1) {
    1.82 +                        fillInCandidate(f, candidates, x, y);
    1.83 +                        fillDistinct = true;
    1.84 +                    }
    1.85 +                }
    1.86 +            }
    1.87 +        } while (fillDistinct);
    1.88 +        
    1.89 +        // Try out remaining candidates
    1.90 +        for (int x = 0 ; x < 9 ; x++) {
    1.91 +            for (int y = 0 ; y < 9 ; y++) {
    1.92 +                if (f.isCellEmpty(x, y)) {
    1.93 +                    while (candidates[x][y].size() > 0) {
    1.94 +                        List<Integer>[][] cb = new List[9][9];
    1.95 +                        makeBackup(candidates, cb);
    1.96 +                        Integer c = fillInCandidate(f, candidates, x, y);
    1.97 +                        if (solve(f, candidates)) {
    1.98 +                            break;
    1.99 +                        } else {
   1.100 +                            f.clearCellValue(x, y);
   1.101 +                            restoreBackup(candidates, cb);
   1.102 +                            // Remove current candidate anyway
   1.103 +                            candidates[x][y].remove(c);
   1.104 +                        }
   1.105 +                    }
   1.106 +                }
   1.107 +                if (f.isCellEmpty(x, y)) {
   1.108 +                    restoreBackup(f, fieldBackup);
   1.109 +                    restoreBackup(candidates, candidatesBackup);
   1.110 +                    return false;
   1.111 +                }
   1.112 +            }
   1.113 +        }
   1.114 +        
   1.115 +        return true;
   1.116 +    }
   1.117 +    
   1.118 +    public boolean solve(Field f) {
   1.119 +        
   1.120 +        // Calculate initial candidates
   1.121 +        List<Integer> candidates[][] = new List[9][9];
   1.122 +        for (int x = 0 ; x < 9 ; x++) {
   1.123 +            for (int y = 0 ; y < 9 ; y++) {
   1.124 +                candidates[x][y] = new ArrayList<>(9);
   1.125 +                if (f.getCellValue(x, y) == 0) {
   1.126 +                    // All numbers are candidates
   1.127 +                    for (int c = 1 ; c <= 9 ; c++) {
   1.128 +                        candidates[x][y].add(c);
   1.129 +                    }
   1.130 +                    // Remove row duplicates
   1.131 +                    int[] line = f.getRow(y);
   1.132 +                    for (Integer c : line) {
   1.133 +                        candidates[x][y].remove(c);
   1.134 +                    }
   1.135 +                    // Remove column duplicates
   1.136 +                    line = f.getColumn(x);
   1.137 +                    for (Integer c : line) {
   1.138 +                        candidates[x][y].remove(c);
   1.139 +                    }
   1.140 +                    // Remove square duplicates
   1.141 +                    int[][] square = f.getSquare(x/3, y/3);
   1.142 +                    for (int[] sq : square) {
   1.143 +                        for (Integer c : sq) {
   1.144 +                            candidates[x][y].remove(c);
   1.145 +                        }
   1.146 +                    }
   1.147 +                }
   1.148 +            }
   1.149 +        }
   1.150 +        
   1.151 +        // Backtrack
   1.152 +        return solve(f, candidates) && complete(f);
   1.153 +    }
   1.154 +    
   1.155      public boolean check(Field f) {
   1.156          int line[];
   1.157          for (int i = 0 ; i < 9 ; i++) {
   1.158 @@ -61,6 +202,25 @@
   1.159          return true;
   1.160      }
   1.161      
   1.162 +    private boolean complete(Field f) {
   1.163 +        for (int i = 0 ; i < 9 ; i++) {
   1.164 +            if (!complete(f.getRow(i))) {
   1.165 +                return false;
   1.166 +            }
   1.167 +            if (!complete(f.getColumn(i))) {
   1.168 +                return false;
   1.169 +            }
   1.170 +        }
   1.171 +        for (int x = 0 ; x < 3 ; x++) {
   1.172 +            for (int y = 0 ; y < 3 ; y++) {
   1.173 +                if (!complete(f.getSquare(x, y))) {
   1.174 +                    return false;
   1.175 +                }
   1.176 +            }
   1.177 +        }
   1.178 +        return true;
   1.179 +    }
   1.180 +    
   1.181      private boolean complete(int[][] square) {
   1.182          for (int x = 0 ; x < 3 ; x++) {
   1.183              for (int y = 0 ; y < 3 ; y++) {

mercurial