public void SolveBoard() { solver.Initialise(sudoku); solver.settings.bruteForce = false; var result = solver.Solve(); Debug.Log(result); for (int i = 0; i < sudoku.settings.numHorizontal; i++) { for (int j = 0; j < sudoku.settings.numVertical; j++) { if (solver.GetValue(i, j) != "") { SetFull(i, j, solver.GetValue(i, j).ToString(), false); } else { boxes[i, j].Clear(false); foreach (string x in solver.final.possible_values[i, j]) { boxes[i, j].ToggleCentre(x, false); } } } } }
public override void PropogateChange(int i, int j, BoardSolver bs) { for (int k = 0; k < bs.final.sudoku.settings.numHorizontal; k++) { if (k != i) { bs.EnsureNotPossible(k, j, bs.GetValue(i, j)); } } for (int k = 0; k < bs.final.sudoku.settings.numVertical; k++) { if (k != j) { bs.EnsureNotPossible(i, k, bs.GetValue(i, j)); } } // Locate the box we are in int boxX = (int)((i / (bs.final.sudoku.settings.numHorizontalThins + 1)) * (bs.final.sudoku.settings.numHorizontalThins + 1)); int boxY = (int)((j / (bs.final.sudoku.settings.numVerticalThins + 1)) * (bs.final.sudoku.settings.numVerticalThins + 1)); for (int a = 0; a < (bs.final.sudoku.settings.numHorizontalThins + 1); a++) { for (int b = 0; b < (bs.final.sudoku.settings.numVerticalThins + 1); b++) { if ((a + boxX != i) || (b + boxY != j)) { bs.EnsureNotPossible(a + boxX, b + boxY, bs.GetValue(i, j)); } } } }
public override List <BoardNotifications.BoardError> GetErrors(BoardSolver bs) { List <BoardNotifications.BoardError> errors = new List <BoardNotifications.BoardError>(); var ts = bs.final.sudoku.GetVariant(VariantList.VariantType.Thermo.ToString()).serializer as ThermoSerializer; for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++) { for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++) { for (int k = 0; k < 4; k++) { (int x, int y)newPos = (i + ThermoSerializer.directions[k, 0], j + ThermoSerializer.directions[k, 1]); if (bs.GetValue(i, j) != "" && bs.GetValue(newPos.x, newPos.y) != "") { int res1, res2; if (!int.TryParse(bs.GetValue(i, j), out res1)) { List <(int x, int y)> boxes = new List <(int x, int y)>(); boxes.Add((i, j)); errors.Add(new BoardNotifications.BoardError( BoardNotifications.ErrorType.SELECTION_INVALID, boxes, "This box must be numeric." )); } else if (!int.TryParse(bs.GetValue(newPos.x, newPos.y), out res2)) { List <(int x, int y)> boxes = new List <(int x, int y)>(); boxes.Add((newPos.x, newPos.y)); errors.Add(new BoardNotifications.BoardError( BoardNotifications.ErrorType.SELECTION_INVALID, boxes, "This box must be numeric." )); } else if (ts.incoming[i, j, k] && res1 <= res2) { List <(int x, int y)> affected = new List <(int x, int y)>(); affected.Add((i, j)); affected.Add((newPos.x, newPos.y)); errors.Add(new BoardNotifications.BoardError( BoardNotifications.ErrorType.SELECTION_INVALID, affected, "Thermo rules require that numbers increase along lines, meaning we require " + bs.GetValue(i, j) + " > " + bs.GetValue(newPos.x, newPos.y) )); } } } } } return(errors); }
public override List <BoardNotifications.BoardError> GetErrors(BoardSolver bs) { List <BoardNotifications.BoardError> errors = new List <BoardNotifications.BoardError>(); var ss = bs.final.sudoku.GetVariant(VariantList.VariantType.Sandwich.ToString()).serializer as SandwichSerializer; foreach (var box in ss.serializedObject.boxes) { if (box.posx == BoxController.topBox || box.posx == BoxController.botBox) { int oneIndex = -1; int oneCounts = 0; int nineIndex = -1; int nineCounts = 0; for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++) { if (bs.GetValue(box.posy, i) == "1") { oneCounts++; oneIndex = i; } if (bs.GetValue(box.posy, i) == "9") { nineCounts++; nineIndex = i; } } if (oneCounts == 1 && nineCounts == 1) { List <(int x, int y)> points = new List <(int x, int y)>(); bool bad = false; for (int i = Mathf.Min(oneIndex, nineIndex) + 1; i < Mathf.Max(oneIndex, nineIndex); i++) { points.Add((box.posy, i)); if (bs.GetValue(box.posy, i) == "") { bad = true; } } if (!bad) { int s = 0; foreach (var v in points) { int res; if (int.TryParse(bs.GetValue(v.x, v.y), out res)) { s += res; } else { List <(int x, int y)> p = new List <(int x, int y)>(); p.Add(v); errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SELECTION_INVALID, p, "This box must be numeric.")); } } if (s != int.Parse(box.answer)) { errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SUM_INVALID, points, "These boxes must sum to " + box.answer)); } } } } else if (box.posy == BoxController.topBox || box.posy == BoxController.botBox) { int oneIndex = -1; int oneCounts = 0; int nineIndex = -1; int nineCounts = 0; for (int j = 0; j < bs.final.sudoku.settings.numHorizontal; j++) { if (bs.GetValue(j, box.posx) == "1") { oneCounts++; oneIndex = j; } if (bs.GetValue(j, box.posx) == "9") { nineCounts++; nineIndex = j; } } if (oneCounts == 1 && nineCounts == 1) { List <(int x, int y)> points = new List <(int x, int y)>(); bool bad = false; for (int j = Mathf.Min(oneIndex, nineIndex) + 1; j < Mathf.Max(oneIndex, nineIndex); j++) { points.Add((j, box.posx)); if (bs.GetValue(j, box.posx) == "") { bad = true; } } if (!bad) { int s = 0; foreach (var v in points) { int res; if (int.TryParse(bs.GetValue(v.x, v.y), out res)) { s += res; } else { List <(int x, int y)> p = new List <(int x, int y)>(); p.Add(v); errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SELECTION_INVALID, p, "This box must be numeric.")); } } if (s != int.Parse(box.answer)) { errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.SUM_INVALID, points, "These boxes must sum to " + box.answer)); } } } } } return(errors); }
public override BoardSolver.SolveResult RestrictGrid(BoardSolver bs) { bool changed = false; for (int v = 1; v <= 9; v++) { for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++) { int v_located = 0; for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++) { if (bs.Allows(i, j, v.ToString())) { v_located++; } } if (v_located == 0) { return(BoardSolver.SolveResult.Impossible); } if (v_located == 1) { for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++) { if (bs.Allows(i, j, v.ToString()) && bs.GetValue(i, j) != v.ToString()) { changed = true; bs.SetValue(i, j, v.ToString()); } } } } for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++) { int v_located = 0; for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++) { if (bs.Allows(i, j, v.ToString())) { v_located++; } } if (v_located == 0) { return(BoardSolver.SolveResult.Impossible); } if (v_located == 1) { for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++) { if (bs.Allows(i, j, v.ToString()) && bs.GetValue(i, j) != v.ToString()) { changed = true; bs.SetValue(i, j, v.ToString()); } } } } for (int a = 0; a < bs.final.sudoku.settings.numHorizontal; a += (int)(bs.final.sudoku.settings.numHorizontalThins + 1)) { for (int b = 0; b < bs.final.sudoku.settings.numVertical; b += (int)(bs.final.sudoku.settings.numVerticalThins + 1)) { // Check for box (a, b) int v_located = 0; for (int x = 0; x < (bs.final.sudoku.settings.numHorizontalThins + 1); x++) { for (int y = 0; y < (bs.final.sudoku.settings.numVerticalThins + 1); y++) { if (bs.Allows(a + x, b + y, v.ToString())) { v_located++; } } } if (v_located == 0) { return(BoardSolver.SolveResult.Impossible); } if (v_located == 1) { for (int x = 0; x < (bs.final.sudoku.settings.numHorizontalThins + 1); x++) { for (int y = 0; y < (bs.final.sudoku.settings.numVerticalThins + 1); y++) { if (bs.Allows(a + x, b + y, v.ToString()) && bs.GetValue(a + x, b + y) != v.ToString()) { changed = true; bs.SetValue(a + x, b + y, v.ToString()); } } } } } } } if (changed) { return(BoardSolver.SolveResult.Solved); } return(BoardSolver.SolveResult.Unchanged); }
public override List <BoardNotifications.BoardError> GetErrors(BoardSolver bs) { List <BoardNotifications.BoardError> errors = new List <BoardNotifications.BoardError>(); for (int v = 1; v <= 9; v++) { for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++) { List <(int x, int y)> boxes = new List <(int x, int y)>(); for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++) { if (bs.GetValue(i, j) == v.ToString()) { boxes.Add((i, j)); } } if (boxes.Count > 1) { errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.COL_INVALID, boxes, "This column can only have a single " + v)); } } for (int j = 0; j < bs.final.sudoku.settings.numVertical; j++) { List <(int x, int y)> boxes = new List <(int x, int y)>(); for (int i = 0; i < bs.final.sudoku.settings.numHorizontal; i++) { if (bs.GetValue(i, j) == v.ToString()) { boxes.Add((i, j)); } } if (boxes.Count > 1) { errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.ROW_INVALID, boxes, "This row can only have a single " + v)); } } for (int a = 0; a < bs.final.sudoku.settings.numHorizontal; a += (int)(bs.final.sudoku.settings.numHorizontalThins + 1)) { for (int b = 0; b < bs.final.sudoku.settings.numVertical; b += (int)(bs.final.sudoku.settings.numVerticalThins + 1)) { // Check for box (a, b) List <(int x, int y)> boxes = new List <(int x, int y)>(); for (int x = 0; x < (bs.final.sudoku.settings.numHorizontalThins + 1); x++) { for (int y = 0; y < (bs.final.sudoku.settings.numVerticalThins + 1); y++) { if (bs.GetValue(a + x, b + y) == v.ToString()) { boxes.Add((a + x, b + y)); } } } if (boxes.Count > 1) { errors.Add(new BoardNotifications.BoardError(BoardNotifications.ErrorType.BOX_INVALID, boxes, "This box can only have a single " + v)); } } } } return(errors); }