aaaaa
Some checks failed
Linux arm64 / Build (push) Failing after 31s

This commit is contained in:
2025-02-02 19:34:21 +01:00
parent 627c49b961
commit 9c72891048
5 changed files with 698 additions and 36 deletions

View File

@@ -1,5 +1,6 @@
package sudoku.solver;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
@@ -8,17 +9,27 @@ import sudoku.structure.MultiDoku;
public class MixedSolver implements Solver {
private Cell findCellToBacktrack(MultiDoku doku, int maxPossibilities) {
private List<Cell> findCellToBacktrack(MultiDoku doku, int maxPossibilities) {
int symbolCount = doku.getSubGrid(0).getSize();
if (maxPossibilities > symbolCount)
return null;
List<Cell> backtrackCells = new ArrayList<>();
for (Cell cell : doku.getCells()) {
if (!cell.isMutable() || !cell.isEmpty())
continue;
List<Integer> possibleSymbols = cell.getPossibleSymbols();
if (possibleSymbols.size() == maxPossibilities) {
return cell;
backtrackCells.add(cell);
}
// grille non résolvable
if (possibleSymbols.size() == 0)
return null;
}
return null;
return backtrackCells;
}
/**
@@ -34,41 +45,54 @@ public class MixedSolver implements Solver {
throw new CancellationException("User wants to stop the solver");
}
while (!doku.isSolved()) {
boolean filledCell = false;
for (Cell cell : doku.getCells()) {
if (!cell.isMutable() || !cell.isEmpty())
continue;
int symbolCount = doku.getSubGrid(0).getSize();
List<Integer> possibleSymbols = cell.getPossibleSymbols();
if (possibleSymbols.size() == 1) {
cell.setSymbolIndex(possibleSymbols.getFirst());
addStep(cell, steps);
filledCell = true;
}
}
// on ne peut plus remplir de cases, on tente de backtrack
if (!filledCell) {
int maxPossibilities = 2;
Cell backtrackCell = null;
while (backtrackCell == null) {
backtrackCell = findCellToBacktrack(doku, maxPossibilities);
maxPossibilities++;
}
// on fait du backtracking
List<Integer> possibilities = backtrackCell.getPossibleSymbols();
for (int symbol : possibilities) {
doku.getStateManager().pushState();
backtrackCell.setSymbolIndex(symbol);
if (solve(doku, steps))
return true;
doku.getStateManager().popState();
}
}
// on remplit les cases par déduction
for (Cell cell : doku.getCells()) {
if (!cell.isMutable() || !cell.isEmpty())
continue;
List<Integer> possibleSymbols = cell.getPossibleSymbols();
if (possibleSymbols.size() == 1) {
cell.setSymbolIndex(possibleSymbols.getFirst());
addStep(cell, steps);
}
}
return true;
if (doku.isSolved())
return true;
// on ne peut plus remplir de cases, on tente de backtrack
for (int maxPossibilities = 2; maxPossibilities <= symbolCount; maxPossibilities++) {
List<Cell> backtrackCells = new ArrayList<>();
while (backtrackCells.isEmpty()) {
backtrackCells = findCellToBacktrack(doku, maxPossibilities);
// grille non résolvable
if (backtrackCells == null) {
return false;
}
maxPossibilities++;
}
// on fait du backtracking
for (Cell backtrackCell : backtrackCells) {
List<Integer> possibilities = backtrackCell.getPossibleSymbols();
// System.out.println("Backtraing on " + backtrackCell);
// on tente de placer chacun des symboles
for (int symbol : possibilities) {
var state = doku.getStateManager().pushState();
backtrackCell.setSymbolIndex(symbol);
if (solve(doku, steps)) {
// doku.getStateManager().forgetState();
return true;
}
doku.getStateManager().popState();
doku.getStateManager().restoreState(state);
}
}
}
return doku.isSolved();
}
}

View File

@@ -25,6 +25,10 @@ public class StateManager {
this.doku = doku;
}
public void forgetState() {
states.pop();
}
public Map<Cell, Integer> pushState() {
states.add(saveState());
return states.getLast();
@@ -42,7 +46,7 @@ public class StateManager {
return currentState;
}
private void restoreState(Map<Cell, Integer> state) {
public void restoreState(Map<Cell, Integer> state) {
for (var entry : state.entrySet()) {
entry.getKey().setSymbolIndex(entry.getValue());
}

View File

@@ -0,0 +1,78 @@
package sudoku.structure;
import java.util.List;
import java.util.Random;
import sudoku.solver.BacktrackingSolver;
import sudoku.solver.HumanSolver;
import sudoku.solver.MixedSolver;
import sudoku.solver.RandomSolver;
import sudoku.solver.Solver;
public class SudokuFiller {
private static boolean isPossiblySolvable(MultiDoku doku) {
for (Cell cell : doku.getEmptyCells()) {
if (cell.getPossibleSymbols().size() == 0)
return false;
}
return true;
}
private static void tryFillRandomCells(MultiDoku doku) {
Random r = new Random();
while (isPossiblySolvable(doku)) {
int cellCount = doku.getEmptyCells().size();
if (cellCount == 0)
return;
Cell cellToFill = doku.getEmptyCells().get(r.nextInt(cellCount));
if (!cellToFill.isEmpty() || !cellToFill.isMutable())
continue;
List<Integer> possibleSymbols = cellToFill.getPossibleSymbols();
int symbolCount = possibleSymbols.size();
// la cellule n'a pas de valeur possible
if (symbolCount == 0)
return;
cellToFill.setSymbolIndex(possibleSymbols.get(r.nextInt(symbolCount)));
}
}
private static void removeRandomCell(MultiDoku doku) {
Random r = new Random();
int cellCount = doku.getFilledCells().size();
doku.getFilledCells().get(r.nextInt(cellCount)).clearCurrentSymbol();
}
private static void makeSolvable(MultiDoku doku) {
while (!isPossiblySolvable(doku)) {
removeRandomCell(doku);
}
Solver solver = new BacktrackingSolver();
boolean solvable = false;
while (!solvable) {
removeRandomCell(doku);
doku.getStateManager().pushState();
solvable = solver.solve(doku);
doku.getStateManager().popState();
System.out.println("eeeeeeeeeeeee");
}
}
private static void fillDoku(MultiDoku doku) {
tryFillRandomCells(doku);
makeSolvable(doku);
}
private static void setCellsImmutable(MultiDoku doku) {
for (Cell cell : doku.getFilledCells())
cell.setImmutable();
}
public static void fillDoku(MultiDoku doku, Difficulty difficulty) {
fillDoku(doku);
setCellsImmutable(doku);
}
}