예제 #1
0
 /**
  * Two ALS are equal if they contain the same indices
  *
  * @param o
  * @return
  */
 @Override
 public boolean equals(Object o) {
   if (o == null) {
     return false;
   }
   if (!(o instanceof Als)) {
     return false;
   }
   Als a = (Als) o;
   return indices.equals(a.indices);
 }
예제 #2
0
 /**
  * Creates a step for a W-Wing. <code>cand1</code> is the candidate for which eliminations can be
  * made, <code>cand2</code> is the connecting candidate. <code>index1</code> and <code>index2
  * </code> are the bivalue cells, {@link #wIndex1} and {@link #wIndex2} are the strong link.
  * <code>elimSet</code> holds all cells where candidates can be eliminated.
  *
  * @param cand1
  * @param cand2
  * @param index1
  * @param index2
  * @param elimSet
  * @param onlyOne
  * @return
  */
 private SolutionStep createWWingStep(
     int cand1, int cand2, int index1, int index2, SudokuSet elimSet, boolean onlyOne) {
   globalStep.reset();
   globalStep.setType(SolutionType.W_WING);
   globalStep.addValue(cand1);
   globalStep.addValue(cand2);
   globalStep.addIndex(index1);
   globalStep.addIndex(index2);
   globalStep.addFin(index1, cand2);
   globalStep.addFin(index2, cand2);
   globalStep.addFin(wIndex1, cand2);
   globalStep.addFin(wIndex2, cand2);
   for (int i = 0; i < elimSet.size(); i++) {
     globalStep.addCandidateToDelete(elimSet.get(i), cand1);
   }
   SolutionStep step = (SolutionStep) globalStep.clone();
   if (onlyOne) {
     return step;
   } else {
     steps.add(step);
   }
   return null;
 }
예제 #3
0
 /**
  * Computes all the additional fields; is done after the initial search to optimize finding
  * doubles.
  *
  * @param finder
  */
 public void computeFields(SudokuStepFinder finder) {
   this.buddies = new SudokuSet();
   for (int i = 1; i <= 9; i++) {
     if ((candidates & Sudoku2.MASKS[i]) != 0) {
       SudokuSet sudokuCandidates = finder.getCandidates()[i];
       indicesPerCandidat[i] = new SudokuSet(indices);
       indicesPerCandidat[i].and(sudokuCandidates);
       buddiesPerCandidat[i] = new SudokuSet();
       Sudoku2.getBuddies(indicesPerCandidat[i], buddiesPerCandidat[i]);
       buddiesPerCandidat[i].andNot(indices);
       buddiesPerCandidat[i].and(finder.getCandidates()[i]);
       buddiesAlsPerCandidat[i] = new SudokuSet(buddiesPerCandidat[i]);
       buddiesAlsPerCandidat[i].or(indicesPerCandidat[i]);
       buddies.or(buddiesPerCandidat[i]);
     }
   }
 }
예제 #4
0
 /**
  * Searches for W-Wings: look for all combinations of bivalue cells with the same candidates. If
  * one is found and it could theoretically eliminate something, a connecting strong link is
  * searched for.
  *
  * @param onlyOne
  * @return
  */
 private SolutionStep getWWing(boolean onlyOne) {
   for (int i = 0; i < sudoku.getCells().length; i++) {
     if (sudoku.getValue(i) != 0 || sudoku.getAnzCandidates(i) != 2) {
       continue;
     }
     // bivalue cell found
     short cell1 = sudoku.getCell(i);
     int cand1 = sudoku.getAllCandidates(i)[0];
     int cand2 = sudoku.getAllCandidates(i)[1];
     // prepare for elimination checks
     preCalcSet1.setAnd(Sudoku2.buddies[i], finder.getCandidates()[cand1]);
     preCalcSet2.setAnd(Sudoku2.buddies[i], finder.getCandidates()[cand2]);
     // check all other cells
     for (int j = i + 1; j < sudoku.getCells().length; j++) {
       if (sudoku.getCell(j) != cell1) {
         // doesnt fit!
         continue;
       }
       // ok, we have a pair; can anything be eliminated?
       elimSet.setAnd(preCalcSet1, Sudoku2.buddies[j]);
       if (!elimSet.isEmpty()) {
         // check for W-Wing for candidate cand1
         SolutionStep step = checkLink(cand1, cand2, i, j, elimSet, onlyOne);
         if (onlyOne && step != null) {
           return step;
         }
       }
       elimSet.setAnd(preCalcSet2, Sudoku2.buddies[j]);
       if (!elimSet.isEmpty()) {
         // check for W-Wing for candidate cand2
         SolutionStep step = checkLink(cand2, cand1, i, j, elimSet, onlyOne);
         if (onlyOne && step != null) {
           return step;
         }
       }
     }
   }
   return null;
 }
예제 #5
0
 /**
  * Try all combinations of three bivalue cells (for xyz: one trivalue and two bivalue cells). The
  * following restrictions are in place:
  *
  * <ul>
  *   <li>The three cells must have exactly three candidates together
  *   <li>The first cell (pivot) must see both other cells (pincers)
  *   <li>The pincers must have exactly one candidate that is the same (candidate z)
  *   <li>z can be excluded from all cells that see both pincers (for xyz they must see the pivot
  *       as well)
  * </ul>
  *
  * @param xyz
  * @param onlyOne
  * @return
  */
 private SolutionStep getWing(boolean xyz, boolean onlyOne) {
   // first get all bivalue/trivalue cells
   int biValueCount = 0;
   int triValueCount = 0;
   for (int i = 0; i < Sudoku2.LENGTH; i++) {
     if (sudoku.getAnzCandidates(i) == 2) {
       biCells[biValueCount++] = i;
     }
     if (xyz && sudoku.getAnzCandidates(i) == 3) {
       triCells[triValueCount++] = i;
     }
   }
   // now iterate them; use local variables to cover xy and xyz
   int endIndex = xyz ? triValueCount : biValueCount;
   int[] biTri = xyz ? triCells : biCells;
   // we check all combinations of bivalue cells (one tri + 2 bi for xyz)
   for (int i = 0; i < endIndex; i++) {
     for (int j = xyz ? 0 : i + 1; j < biValueCount; j++) {
       // any given combination of two cells must give exactly three
       // candidates; if that is not the case, skip it right away
       if (Sudoku2.ANZ_VALUES[sudoku.getCell(biTri[i]) | sudoku.getCell(biCells[j])] != 3) {
         // cant become a wing
         continue;
       }
       for (int k = j + 1; k < biValueCount; k++) {
         int index1 = biTri[i];
         int index2 = biCells[j];
         int index3 = biCells[k];
         int cell1 = sudoku.getCell(index1);
         int cell2 = sudoku.getCell(index2);
         int cell3 = sudoku.getCell(index3);
         // all three cells combined must have exactly three candidates
         if (Sudoku2.ANZ_VALUES[cell1 | cell2 | cell3] != 3) {
           // incorrect number of candidates
           continue;
         }
         // none of the cells may be equal
         if (cell1 == cell2 || cell2 == cell3 || cell3 == cell1) {
           // cant be a wing
           continue;
         }
         // three possibilities for XY-Wing: each cell could be the pincer
         // XYZ-Wing exits the loop after the first iteration
         int maxTries = xyz ? 1 : 3;
         for (int tries = 0; tries < maxTries; tries++) {
           // swap cells accordingly
           if (tries == 1) {
             index1 = biCells[j];
             index2 = biTri[i];
             cell1 = sudoku.getCell(index1);
             cell2 = sudoku.getCell(index2);
           } else if (tries == 2) {
             index1 = biCells[k];
             index2 = biCells[j];
             index3 = biTri[i];
             cell1 = sudoku.getCell(index1);
             cell2 = sudoku.getCell(index2);
             cell3 = sudoku.getCell(index3);
           }
           // the pivot must see the pincers
           if (!Sudoku2.buddies[index1].contains(index2)
               || !Sudoku2.buddies[index1].contains(index3)) {
             // doesnt see them -> try another
             continue;
           }
           // the pincers must have exactly one candidate that is the same in both cells
           short cell = (short) (cell2 & cell3);
           if (Sudoku2.ANZ_VALUES[cell] != 1) {
             // no wing, sorry
             continue;
           }
           int candZ = Sudoku2.CAND_FROM_MASK[cell];
           // are there candidates that can see the pincers?
           elimSet.setAnd(Sudoku2.buddies[index2], Sudoku2.buddies[index3]);
           elimSet.and(finder.getCandidates()[candZ]);
           if (xyz) {
             // the pivot as well
             elimSet.and(Sudoku2.buddies[index1]);
           }
           if (elimSet.isEmpty()) {
             // no candidates to delete
             continue;
           }
           // ok, wing found!
           globalStep.reset();
           if (xyz) {
             globalStep.setType(SolutionType.XYZ_WING);
           } else {
             globalStep.setType(SolutionType.XY_WING);
           }
           int[] cands = sudoku.getAllCandidates(index1);
           globalStep.addValue(cands[0]);
           globalStep.addValue(cands[1]);
           if (xyz) {
             globalStep.addValue(cands[2]);
           } else {
             globalStep.addValue(candZ);
           }
           globalStep.addIndex(index1);
           globalStep.addIndex(index2);
           globalStep.addIndex(index3);
           if (xyz) {
             globalStep.addFin(index1, candZ);
           }
           globalStep.addFin(index2, candZ);
           globalStep.addFin(index3, candZ);
           for (int l = 0; l < elimSet.size(); l++) {
             globalStep.addCandidateToDelete(elimSet.get(l), candZ);
           }
           SolutionStep step = (SolutionStep) globalStep.clone();
           if (onlyOne) {
             return step;
           } else {
             steps.add(step);
           }
         }
       }
     }
   }
   return null;
 }