C++ program that solves sudoku [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am writing a C++ code for a Sudoku solver.
The code must work for a 9x9, 16x16 and 25x25 grid. My code only works for a 9x9 grid. I am not sure why. May someone please help me. I think I need to make the 16x16 and 25x25 codes work faster somehow. How do I do this?
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
vector<int> tokenize(string s, string del);
void readAPuzzle(vector<vector<int>> &grid);
void printGrid(vector<vector<int>> grid);
bool isValid(int i, int j, vector<vector<int>> grid);
bool isValid(vector<vector<int>> grid);
bool search(vector<vector<int>> &grid);
int getFreeCellList(vector<vector<int>> grid, vector<pair<int, int>> &freeCellList);
int main()
{
// Read a Sudoku puzzle
vector<vector<int>> puzzle;
readAPuzzle(puzzle);
if (!isValid(puzzle))
cout << "Invalid input" << endl;
else if (search(puzzle)){
printGrid(puzzle);
}
else
cout << "No solution" << endl;
return 0;
}
vector<int> tokenize(string s, string del)
{
vector<int> row;
int start = 0;
int end = s.find(del);
while (end != -1) {
row.push_back(stoi( s.substr(start, end - start)));
start = end + del.size();
end = s.find(del, start);
}
row.push_back(stoi( s.substr(start, end - start)));
return row;
}
void readAPuzzle(vector<vector<int>> &grid){
string line;
getline(cin, line);
vector<int> firstRow = tokenize(line, " ");
grid.push_back(firstRow);
for(int i = 0; i < firstRow.size()-1; i++){
getline(cin, line);
vector<int> row = tokenize(line, " ");
grid.push_back(row);
}
}
/** Obtain a list of free cells from the puzzle */
int getFreeCellList(vector<vector<int>> grid, vector<pair<int, int>> &freeCellList)
{
// 81 is the maximum number of free cells
int numberOfFreeCells = 0;
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if (grid[i][j] == 0)
{
freeCellList[numberOfFreeCells].first = i;
freeCellList[numberOfFreeCells].second = j;
numberOfFreeCells++;
}
return numberOfFreeCells;
}
/** Print the values in the grid */
void printGrid(vector<vector<int>> grid)
{
for (int i = 0; i < grid.size(); i++)
{
for (int j = 0; j < grid.size(); j++)
cout << grid[i][j] << " ";
cout << endl;
}
}
/** Search for a solution */
bool search(vector<vector<int>> &grid)
{
int k = 0; // Start from the first free cell
bool found = false; // Solution found?
const int n = grid.size();
vector<pair<int, int>> freeCellList(n*n);
int numberOfFreeCells = getFreeCellList(grid, freeCellList);
while (!found)
{
int i = freeCellList[k].first;
int j = freeCellList[k].second;
if (grid[i][j] == 0)
grid[i][j] = 1; // Start with 1
if (isValid(i, j, grid))
{
if (k + 1 == numberOfFreeCells)
{ // No more free cells
found = true; // A solution is found
}
else
{ // Move to the next free cell
k++;
}
}
else if (grid[i][j] < grid.size())
{
grid[i][j] = grid[i][j] + 1; // Check the next possible value
}
else
{ // grid[i][j] is 9, backtrack
while (grid[i][j] == grid.size())
{
grid[i][j] = 0; // Reset to free cell
if (k == 0)
{
return false; // No possible value
}
k--; // Backtrack
i = freeCellList[k].first;
j = freeCellList[k].second;
}
grid[i][j] = grid[i][j] + 1; // Check the next possible value
}
}
return true; // A solution is found
}
/** Check whether grid[i][j] is valid in the grid */
bool isValid(int i, int j, vector<vector<int>> grid)
{
// Check whether grid[i][j] is valid at the i's row
for (int column = 0; column < grid.size(); column++)
if (column != j && grid[i][column] == grid[i][j])
return false;
// Check whether grid[i][j] is valid at the j's column
for (int row = 0; row < grid.size(); row++)
if (row != i && grid[row][j] == grid[i][j])
return false;
int n = sqrt(grid.size());
// Check whether grid[i][j] is valid in the 3 by 3 box
for (int row = (i / n) * n; row < (i / n) * n + n; row++)
for (int col = (j / n) * n; col < (j / n) * n + n; col++)
if (row != i && col != j && grid[row][col] == grid[i][j])
return false;
return true; // The current value at grid[i][j] is valid
}
/** Check whether the fixed cells are valid in the grid */
bool isValid(vector<vector<int>> grid)
{
// Check for duplicate numbers
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if (grid[i][j] != 0)
if (!isValid(i, j, grid))
return false;
// Check whether numbers are in the range
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if ((grid[i][j] < 0) || (grid[i][j] > 9))
return false;
return true; // The fixed cells are valid
}
This is the code I have written so far.
Thank you.

In bool isValid(vector<vector<int>>) you have
if ((grid[i][j] < 0) || (grid[i][j] > 9))
return false;
ie a grid with a number > 9 is never considered valid. I cannot tell if there are other errors, but when you only allow numbers in [0,9] it cannot work for 16x16 or 25x25 sized grids.
You are passing the grid by value to some of the functions. You should pass them as const reference instead to avoid unnecessary copies.

Related

N Queen using C++ with Dynamic 2D Array

I have been having difficulty solving the N Queen problem, I am able to implement most of my functions, but the function that places the Queen recursively with backtracking. The placeQueens function is using a provided pseudocode that is required for the project. I had to create the array on the heap that is pointing to boardPtr, which is also required. I have a while loop condition that I have but I am not sure if it's correct. I have tried looking online for similar code but none of them were able to help me.
Here is my code:
#include <iostream>
#include "ChessBoard.h"
int main()
{
// Create a board
ChessBoard myBoard;
/* Loop through board sizes from 3 to 13.
Since 3 and 13 are invalid you should see
board sizes 4 and 12 twice. */
for (int i = 3; i <= 13; i++)
{
myBoard.setSize(i);
/* Attempt to solve the N-Queens Problem. If the solve
code is working it should find solutions for all
sizes. */
if (!myBoard.solve())
std::cout << "Sorry, no solution was found for board size "
<< myBoard.getSize() << "." << std::endl << std::endl;
else
{
std::cout << "Size " << myBoard.getSize()
<< " solution:" << std::endl;
myBoard.displayBoard();
std::cout << std::endl << std::endl;
}
}
return 0;
}
#include "ChessBoard.h"
#include <iostream>
using namespace std;
bool ChessBoard::placeQueens( int column)
{
int row = 0;
if (column >= boardSize)
{
// The board is filled, problem is solved.
return true;
}
else
{
while (row < boardSize && column < boardSize) // unconsidered rows exist in column
{
if ((canPlace(boardPtr, row, column)) == true) //[row][column] is unattacked
{
//Place a queen in the un - attacked square.
boardPtr[row][column] = 'Q';
//Do a recursive call to try and place queens in subsequent columns :
if (!placeQueens(column + 1))
{
//If we’re here, placement of the last queen resulted in a dead end; no solution could be found.Remove the last queen placed.
boardPtr[row][column] = '*';
//Move to next row so search can continue in next iteration.
row++;
}
else
{
// If we’re here, recursive calls were able to place queens in all columns to the right of column, the problem is solved.
return true;
}
}
else
{
//Square is attacked, move to next row.
row++;
}
}
//All rows have been considered in column without a successful queen placement.Backtrack by returning false.
return false;
}
}
bool ChessBoard::canPlace(char** boardPtr, int row, int column)
{
int i, j;
// Check row
for (i = 0; i < column; i++)
if (boardPtr[row][i] )
return false;
// Check upper diagonal
for (i = row, j = column; i >= 0 && j >= 0; i--, j--)
if (boardPtr[i][j])
return false;
// Check lower diagonal
for (i = row, j = column; j >= 0 && i < boardSize; i++, j--)
if (boardPtr[i][j] )
return false;
return true;
}
ChessBoard::ChessBoard()
{
boardSize = 8;
boardPtr = nullptr;
}
ChessBoard::ChessBoard(int size)
{
if (size < 4)
{
boardSize = 4;
}
else if (size > 12)
{
boardSize = 12;
}
}
ChessBoard::~ChessBoard()
{
}
int ChessBoard::setSize(int size)
{
delete[] boardPtr;
//Initialize array at size 4
if (size < 4)
{
boardSize = 4;
char** chessBoard = new char* [4];
for (int i = 0; i < 4; i++)
{
chessBoard[i] = new char[4];
}
// Point initialized ChessBoard to boardPtr
boardPtr = chessBoard;
// Fill ChessBoard with *
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
boardPtr[i][j] = '*';
}
}
}
//Initialize array at size 12
else if (size > 12)
{
boardSize = 12;
char** chessBoard = new char* [12];
for (int i = 0; i < size; i++)
{
chessBoard[i] = new char[12];
}
// Point initialized ChessBoard to boardPtr
boardPtr = chessBoard;
// Fill ChessBoard with *
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
boardPtr[i][j] = '*';
}
}
}
//Initialize array at given size
else
{
boardSize = size;
char** chessBoard = new char* [size];
for (int i = 0; i < size; i++)
{
chessBoard[i] = new char[size];
}
// Point initialized ChessBoard to boardPtr
boardPtr = chessBoard;
// Fill ChessBoard with *
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
boardPtr[i][j] = '*';
}
}
}
return 1;
}
int ChessBoard::getSize()
{
return boardSize;
}
bool ChessBoard::solve()
{
int column = 0;
if (placeQueens(column) == false)
{
return false;
}
else
{
return true;
}
}
void ChessBoard::displayBoard()
{
for (int i = 0; i < boardSize; i++)
{
for (int j = 0; j < boardSize; j++)
{
cout << boardPtr[i][j] << " ";
}
cout << endl;
}
}
#ifndef CHESSBOARD_H
#define CHESSBOARD_H
class ChessBoard
{
private:
char** boardPtr;
int boardSize;
bool placeQueens( int column);
bool canPlace(char** boardPtr, int row, int col);
public:
ChessBoard();
ChessBoard(int size);
~ChessBoard();
int setSize(int size);
int getSize();
bool solve();
void displayBoard();
};
#endif
Interesting task you have! I decided to implement my own code from scratch for solving N Queen problem. Actually I implemented it for any board size N, not just equal to 8.
I didn't fix bugs in your code, but instead implemented my own solution. Although it may be not the answer you want, still it would be a good thing from educational point of view. Hoping that there would be other answers later that are fixing bugs in your code, as you wished.
I made code very optimized, so it is not very simple from first side, but solves task very fast, using BackTracking, with several extra techniques of speeding it up.
After program finishes it prints to console all solutions in a nice form. Please scroll down below the code to see example of console output.
First program has some extra descriptive comments to show what's happenning in program.
Notice that I provided two codes below, first is simplified version, that is more easy to understand, so it is better from educational point of view. Second code is advanced one, it is more difficult, but solves task fast. Please look at first code if you want just to learn basics, and look at second code if you want to learn advanced techniques.
Simplified:
Try it online!
#include <iostream>
#include <vector>
#include <string>
void Output(std::vector<std::vector<bool>> & board, std::vector<std::string> & lines, bool last);
void Solve(std::vector<std::vector<bool>> & board, std::vector<std::string> & lines,
int N, int & num_sol, int cnt = 0, int start_i = 0, int start_j = 0, int depth = 0) {
if (cnt >= N) {
Output(board, lines, false);
// Increase number of solutions.
++num_sol;
return;
}
// Traverse whole board starting from last queen
for (int i = start_i; i < board.size(); ++i)
for (int j = i == start_i ? start_j : 0; j < board[i].size(); ++j) {
bool attacked = false;
// k-loop checks if position [i][j] is being attacked
for (int k = 0; k < (board.size() > board[i].size() ?
board.size() : board[i].size()); ++k)
if (
// Is there horizontal attack
k < board[i].size() && k != j && board[i][k] ||
// Is there vertical attack
k < board.size() && k != i && board[k][j] ||
// Is there main diagonal attack
k < board.size() && k != i && 0 <= j - i + k &&
j - i + k < board[i].size() && board[k][j - i + k] ||
// Is there secondary diagonal attack
k < board.size() && k != i && 0 <= j + i - k &&
j + i - k < board[i].size() && board[k][j + i - k]
) {
attacked = true;
break;
}
if (attacked)
continue;
// Position [i][j] is not under attack, hence placing a queen
board[i][j] = true;
// Recursive descend to place another queen
Solve(board, lines, N, num_sol, cnt + 1, i, j + 1, depth + 1);
// Backtrack, to delete previous queen
board[i][j] = false;
}
if (depth == 0)
Output(board, lines, true);
}
// Function of outputting solutions to console
void Output(std::vector<std::vector<bool>> & board, std::vector<std::string> & lines, bool last) {
if (1) {
if (!last) {
for (int i = 0; i < board.size(); ++i) {
for (int j = 0; j < board[i].size(); ++j)
lines[i].push_back(board[i][j] ? 'Q' : '.');
lines[i] += "|";
}
}
if (lines.at(0).size() >= 70 || last && !lines.at(0).empty()) {
for (int i = 0; i < lines.size(); ++i)
std::cout << lines[i] << std::endl;
for (int j = 0; j < lines.at(0).size(); ++j)
std::cout << (lines.at(0)[j] == '|' ? '+' : '-');
std::cout << std::endl;
lines.clear();
lines.resize(board.size());
}
}
}
int main() {
// rows - number of rows in a board, cols - number of columns in a board
// N - number of queens to be placed
int const rows = 8, cols = 8, N = 8;
// Filling with empty values board [rows][cols]
std::vector<std::vector<bool>> board(rows, std::vector<bool>(cols));
std::vector<std::string> lines(rows);
// Answer, number of solutions
int num_sol = 0;
// Starting a backtracking
Solve(board, lines, N, num_sol);
// Outputting answer
std::cout << "Number of solutions: " << num_sol << std::endl;
}
Advanced:
Try it online!
#include <iostream>
#include <string>
#define MAX(a, b) ((a) >= (b) ? (a) : (b))
enum { max_rows = 32, max_cols = 32, max_max_rows_cols = MAX(max_rows, max_cols) };
void Output(bool (& board)[max_rows][max_cols], std::string (& lines)[max_rows],
int rows, int cols, bool last);
void Solve(bool (& board)[max_rows][max_cols], std::string (& lines)[max_rows],
bool (& busy_cols)[max_cols], bool (& busy_diagA)[2 * max_max_rows_cols],
bool (& busy_diagB)[2 * max_max_rows_cols],
int rows, int cols, int N, int & num_sol, int cnt = 0, int start_i = 0, int depth = 0) {
if (cnt >= N) {
Output(board, lines, rows, cols, false);
++num_sol;
return;
}
int const max_rows_cols = MAX(rows, cols);
if (rows - start_i < N - cnt)
return;
int avail_cols[max_cols];
int avail_cols_cnt = 0;
for (int j = 0; j < cols; ++j)
if (!busy_cols[j]) {
avail_cols[avail_cols_cnt] = j;
++avail_cols_cnt;
}
if (avail_cols_cnt < N - cnt)
return;
for (int i = start_i; i < rows; ++i)
for (int jj = 0; jj < avail_cols_cnt; ++jj) {
int const j = avail_cols[jj];
if (busy_diagA[max_rows_cols + j - i] || busy_diagB[j + i])
continue;
board[i][j] = true;
busy_cols[j] = true;
busy_diagA[max_rows_cols + j - i] = true;
busy_diagB[j + i] = true;
Solve(board, lines, busy_cols, busy_diagA, busy_diagB,
rows, cols, N, num_sol, cnt + 1, i + 1, depth + 1);
board[i][j] = false;
busy_cols[j] = false;
busy_diagA[max_rows_cols + j - i] = false;
busy_diagB[j + i] = false;
}
if (depth == 0)
Output(board, lines, rows, cols, true);
}
void Output(bool (& board)[max_rows][max_cols], std::string (& lines)[max_rows],
int rows, int cols, bool last) {
if (1) {
if (!last) {
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j)
lines[i].push_back(board[i][j] ? 'Q' : '.');
lines[i] += "|";
}
}
if (lines[0].size() >= 70 || last && !lines[0].empty()) {
for (int i = 0; i < rows; ++i)
std::cout << lines[i] << std::endl;
for (int j = 0; j < lines[0].size(); ++j)
std::cout << (lines[0][j] == '|' ? '+' : '-');
std::cout << std::endl;
for (int i = 0; i < rows; ++i)
lines[i].clear();
}
}
}
int main() {
int const rows = 8, cols = 8, N = 8;
bool board[max_rows][max_cols] = {};
std::string lines[max_rows] = {};
bool busy_cols[max_cols] = {};
bool busy_diagA[2 * max_max_rows_cols] = {};
bool busy_diagB[2 * max_max_rows_cols] = {};
int num_sol = 0;
Solve(board, lines, busy_cols, busy_diagA, busy_diagB, rows, cols, N, num_sol);
std::cout << "Number of solutions: " << num_sol << std::endl;
}
Output:
Q.......|Q.......|Q.......|Q.......|.Q......|.Q......|.Q......|.Q......|
....Q...|.....Q..|......Q.|......Q.|...Q....|....Q...|....Q...|.....Q..|
.......Q|.......Q|...Q....|....Q...|.....Q..|......Q.|......Q.|Q.......|
.....Q..|..Q.....|.....Q..|.......Q|.......Q|Q.......|...Q....|......Q.|
..Q.....|......Q.|.......Q|.Q......|..Q.....|..Q.....|Q.......|...Q....|
......Q.|...Q....|.Q......|...Q....|Q.......|.......Q|.......Q|.......Q|
.Q......|.Q......|....Q...|.....Q..|......Q.|.....Q..|.....Q..|..Q.....|
...Q....|....Q...|..Q.....|..Q.....|....Q...|...Q....|..Q.....|....Q...|
--------+--------+--------+--------+--------+--------+--------+--------+
.Q......|.Q......|.Q......|.Q......|..Q.....|..Q.....|..Q.....|..Q.....|
.....Q..|......Q.|......Q.|.......Q|Q.......|....Q...|....Q...|....Q...|
.......Q|..Q.....|....Q...|.....Q..|......Q.|.Q......|.Q......|......Q.|
..Q.....|.....Q..|.......Q|Q.......|....Q...|.......Q|.......Q|Q.......|
Q.......|.......Q|Q.......|..Q.....|.......Q|Q.......|.....Q..|...Q....|
...Q....|....Q...|...Q....|....Q...|.Q......|......Q.|...Q....|.Q......|
......Q.|Q.......|.....Q..|......Q.|...Q....|...Q....|......Q.|.......Q|
....Q...|...Q....|..Q.....|...Q....|.....Q..|.....Q..|Q.......|.....Q..|
--------+--------+--------+--------+--------+--------+--------+--------+
..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|
....Q...|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|
.......Q|.Q......|.Q......|.Q......|...Q....|...Q....|.......Q|.......Q|
...Q....|....Q...|......Q.|......Q.|Q.......|.Q......|Q.......|Q.......|
Q.......|.......Q|Q.......|....Q...|.......Q|.......Q|...Q....|....Q...|
......Q.|Q.......|...Q....|Q.......|....Q...|....Q...|......Q.|......Q.|
.Q......|......Q.|.......Q|.......Q|......Q.|......Q.|....Q...|.Q......|
.....Q..|...Q....|....Q...|...Q....|.Q......|Q.......|.Q......|...Q....|
--------+--------+--------+--------+--------+--------+--------+--------+
..Q.....|..Q.....|..Q.....|..Q.....|...Q....|...Q....|...Q....|...Q....|
.....Q..|......Q.|......Q.|.......Q|Q.......|Q.......|.Q......|.Q......|
.......Q|.Q......|.Q......|...Q....|....Q...|....Q...|....Q...|......Q.|
.Q......|.......Q|.......Q|......Q.|.......Q|.......Q|.......Q|..Q.....|
...Q....|....Q...|.....Q..|Q.......|.Q......|.....Q..|.....Q..|.....Q..|
Q.......|Q.......|...Q....|.....Q..|......Q.|..Q.....|Q.......|.......Q|
......Q.|...Q....|Q.......|.Q......|..Q.....|......Q.|..Q.....|Q.......|
....Q...|.....Q..|....Q...|....Q...|.....Q..|.Q......|......Q.|....Q...|
--------+--------+--------+--------+--------+--------+--------+--------+
...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|
.Q......|.Q......|.Q......|.Q......|.....Q..|.....Q..|.....Q..|......Q.|
......Q.|......Q.|.......Q|.......Q|Q.......|.......Q|.......Q|Q.......|
..Q.....|....Q...|....Q...|.....Q..|....Q...|.Q......|..Q.....|.......Q|
.....Q..|Q.......|......Q.|Q.......|.Q......|......Q.|Q.......|....Q...|
.......Q|.......Q|Q.......|..Q.....|.......Q|Q.......|......Q.|.Q......|
....Q...|.....Q..|..Q.....|....Q...|..Q.....|..Q.....|....Q...|.....Q..|
Q.......|..Q.....|.....Q..|......Q.|......Q.|....Q...|.Q......|..Q.....|
--------+--------+--------+--------+--------+--------+--------+--------+
...Q....|...Q....|...Q....|...Q....|...Q....|...Q....|....Q...|....Q...|
......Q.|......Q.|......Q.|.......Q|.......Q|.......Q|Q.......|Q.......|
..Q.....|....Q...|....Q...|Q.......|Q.......|....Q...|...Q....|.......Q|
.......Q|.Q......|..Q.....|..Q.....|....Q...|..Q.....|.....Q..|...Q....|
.Q......|.....Q..|Q.......|.....Q..|......Q.|Q.......|.......Q|.Q......|
....Q...|Q.......|.....Q..|.Q......|.Q......|......Q.|.Q......|......Q.|
Q.......|..Q.....|.......Q|......Q.|.....Q..|.Q......|......Q.|..Q.....|
.....Q..|.......Q|.Q......|....Q...|..Q.....|.....Q..|..Q.....|.....Q..|
--------+--------+--------+--------+--------+--------+--------+--------+
....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|
Q.......|.Q......|.Q......|.Q......|.Q......|..Q.....|..Q.....|..Q.....|
.......Q|...Q....|...Q....|.....Q..|.......Q|Q.......|Q.......|.......Q|
.....Q..|.....Q..|......Q.|Q.......|Q.......|.....Q..|......Q.|...Q....|
..Q.....|.......Q|..Q.....|......Q.|...Q....|.......Q|.Q......|......Q.|
......Q.|..Q.....|.......Q|...Q....|......Q.|.Q......|.......Q|Q.......|
.Q......|Q.......|.....Q..|.......Q|..Q.....|...Q....|.....Q..|.....Q..|
...Q....|......Q.|Q.......|..Q.....|.....Q..|......Q.|...Q....|.Q......|
--------+--------+--------+--------+--------+--------+--------+--------+
....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|....Q...|
......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|.......Q|.......Q|
Q.......|Q.......|.Q......|.Q......|.Q......|...Q....|...Q....|...Q....|
..Q.....|...Q....|...Q....|.....Q..|.....Q..|Q.......|Q.......|Q.......|
.......Q|.Q......|.......Q|..Q.....|..Q.....|..Q.....|..Q.....|......Q.|
.....Q..|.......Q|Q.......|Q.......|Q.......|.......Q|.....Q..|.Q......|
...Q....|.....Q..|..Q.....|...Q....|.......Q|.....Q..|.Q......|.....Q..|
.Q......|..Q.....|.....Q..|.......Q|...Q....|.Q......|......Q.|..Q.....|
--------+--------+--------+--------+--------+--------+--------+--------+
.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|
Q.......|.Q......|.Q......|..Q.....|..Q.....|..Q.....|..Q.....|..Q.....|
....Q...|......Q.|......Q.|Q.......|Q.......|Q.......|....Q...|....Q...|
.Q......|Q.......|Q.......|......Q.|.......Q|.......Q|......Q.|.......Q|
.......Q|..Q.....|...Q....|....Q...|...Q....|....Q...|Q.......|Q.......|
..Q.....|....Q...|.......Q|.......Q|.Q......|.Q......|...Q....|...Q....|
......Q.|.......Q|....Q...|.Q......|......Q.|...Q....|.Q......|.Q......|
...Q....|...Q....|..Q.....|...Q....|....Q...|......Q.|.......Q|......Q.|
--------+--------+--------+--------+--------+--------+--------+--------+
.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|.....Q..|
..Q.....|..Q.....|..Q.....|...Q....|...Q....|...Q....|...Q....|.......Q|
......Q.|......Q.|......Q.|Q.......|.Q......|......Q.|......Q.|.Q......|
.Q......|.Q......|...Q....|....Q...|.......Q|Q.......|Q.......|...Q....|
...Q....|.......Q|Q.......|.......Q|....Q...|..Q.....|.......Q|Q.......|
.......Q|....Q...|.......Q|.Q......|......Q.|....Q...|.Q......|......Q.|
Q.......|Q.......|.Q......|......Q.|Q.......|.Q......|....Q...|....Q...|
....Q...|...Q....|....Q...|..Q.....|..Q.....|.......Q|..Q.....|..Q.....|
--------+--------+--------+--------+--------+--------+--------+--------+
......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|......Q.|
Q.......|.Q......|.Q......|..Q.....|..Q.....|...Q....|...Q....|....Q...|
..Q.....|...Q....|.....Q..|Q.......|.......Q|.Q......|.Q......|..Q.....|
.......Q|Q.......|..Q.....|.....Q..|.Q......|....Q...|.......Q|Q.......|
.....Q..|.......Q|Q.......|.......Q|....Q...|.......Q|.....Q..|.....Q..|
...Q....|....Q...|...Q....|....Q...|Q.......|Q.......|Q.......|.......Q|
.Q......|..Q.....|.......Q|.Q......|.....Q..|..Q.....|..Q.....|.Q......|
....Q...|.....Q..|....Q...|...Q....|...Q....|.....Q..|....Q...|...Q....|
--------+--------+--------+--------+--------+--------+--------+--------+
.......Q|.......Q|.......Q|.......Q|
.Q......|.Q......|..Q.....|...Q....|
...Q....|....Q...|Q.......|Q.......|
Q.......|..Q.....|.....Q..|..Q.....|
......Q.|Q.......|.Q......|.....Q..|
....Q...|......Q.|....Q...|.Q......|
..Q.....|...Q....|......Q.|......Q.|
.....Q..|.....Q..|...Q....|....Q...|
--------+--------+--------+--------+
Number of solutions: 92
There are several issues, starting from the multiple memory leaks (see e.g. the empty destructor or the delete[] boardPtr; at the beginning of ChessBoard::setSize), but what prevents the program to solve the problem is this:
bool ChessBoard::canPlace(char** boardPtr, int row, int column)
{
int i, j;
// Check row
for (i = 0; i < column; i++)
if (boardPtr[row][i] )
// ^^^^^^^^^^^^^^^^
return false;
// ...
}
That condition and the following ones should be boardPtr[row][i] == 'Q', because, as written, it just check if the char is not 0, while an empty spot is indicated by a . in this program.

why there is a mistake in the third board? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I assume that everyone has heard of the game, but if not - here is a link:
https://bitstorm.org/gameoflife/
I'm trying to implement it in C++ without using structs, classes etc.
So far I've done this:
#define N 10
#define M 10
#include <iostream>
bool** createGrid(int n, int m)
{
bool** grid = new bool*[n];
for (int i = 0; i < n; i++)
grid[i] = new bool[m];
return grid;
}
void displayGrid(bool** grid, int n, int m)
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (grid[i][j] == 1)
std::cout << 'X';
else
std::cout << '.';
}
std::cout << std::endl;
}
std::cout << "##########\n";
}
void releaseGrid(bool** grid, int n)
{
for (int i = 0; i < n; i++)
delete[] grid[i];
delete[] grid;
}
int countAliveNeighbours(bool** grid, int k, int l)
{
int aliveNeighbours = 0;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
aliveNeighbours += grid[k + i][l + j];
// The cell needs to be subtracted from it's neighbours as it was counted before
aliveNeighbours -= grid[k][l];
return aliveNeighbours;
}
bool** nextGeneration(bool** grid, int n, int m)
{
bool** next = createGrid(n, m);
// Loop through every cell
for (int k = 1; k < n - 1; k++) {
for (int l = 1; l < m - 1; l++) {
// finding count of neighbours that are alive
int aliveNeighbours = countAliveNeighbours(grid, k, l);
// Implementing the Rules of Life
// Cell is lonely and dies
if ((grid[k][l] == 1) && (aliveNeighbours < 2))
next[k][l] = 0;
// Cell dies due to over population
else if ((grid[k][l] == 1) && (aliveNeighbours > 3))
next[k][l] = 0;
// A new cell is born
else if ((grid[k][l] == 0) && (aliveNeighbours == 3))
next[k][l] = 1;
// Remains the same
else
next[k][l] = grid[k][l];
}
}
return next;
}
bool checksTwoGridsForDifferences(bool** prevGrid, bool** nextGrid, int n, int m)
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (prevGrid[i][j] != nextGrid[i][j]) {
return true;
}
}
}
return false;
}
void fillGrid(bool** grid, int n, int m)
{
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
grid[i][j] = 0;
}
}
grid[1][3] = 1;
grid[1][4] = 1;
grid[2][4] = 1;
grid[5][3] = 1;
grid[5][4] = 1;
grid[6][2] = 1;
grid[6][3] = 1;
grid[7][5] = 1;
grid[8][4] = 1;
}
int main()
{
bool** prevGrid = createGrid(N, M); // create starting grid
fillGrid(prevGrid, N, M); // fill starting grid
std::cout << "Starting grid:\n";
displayGrid(prevGrid, N, M); // display starting grid
bool** nextGrid = nextGeneration(prevGrid, N, M); //generate next grid
while (checksTwoGridsForDifferences(prevGrid, nextGrid, N, M)) {
displayGrid(nextGrid, N, M);
releaseGrid(prevGrid, N);
prevGrid = nextGrid;
nextGrid = nextGeneration(prevGrid, N, M);
}
releaseGrid(nextGrid, N);
releaseGrid(prevGrid, N);
return 0;
}
but I'm stuck, becаuse the third grid is not correct (It wrongly erases two Xs), and I wonder why? Can anyone show me the mistake?
It shows:
..........
..........
...XX.....
..........
...X......
..X.X.....
..........
..XXX.....
..........
..........
instead of:
..........
...XX.....
...XX.....
..........
...X......
..X.X.....
..........
..XXX.....
..........
..........
The problem is that you are not filling in the edges of your next generation grid. The comment // Loop through every cell in nextGeneration is not true because you skip the edges of your grid.
You need to work a bit harder in your countAliveNeighbours function so you don't step over the edge of the grid, and then change your nextGeneration function so that you really do loop through every cell. Or you could have the edges of the grid permanently switched off.
I found this problem in about two minutes using a debugger. I couldn't see it by looking at the code. You really should teach yourself how to use a debugger. It's the biggest step up you'll ever make in your productivity as a programmer.
Well posed question BTW, enough information to easily solve the problem.

How to check if a char in a 2d array appears more than once? c++

I'm making a board game, and I was just wondering how to search through an array to find an element (let's name it N in this case), and each time N is counted, the counter goes up one. If N connects one side to the other the player wins.
This solution is only for one row of the array, hence why the counter is reset at the start of each 'i' iteration.
void board::winner(int x, int y)
{
int count = 0;
for (int i = 0; i < col; i++)
{
count = 0;
for (int j = 0; j < row; xaxis++)
{
if (arr[i][j] == 'N')
{
count++;
}
}
if (count == col) // == to col because we are testing straight lines
{
cout << "P2 wins!";
}
}
Move you initialization of count to above the first for loop.
Move the if statement after the end of the first for loop.
void board::winner(int x, int y)
{
int count = 0;
for (int i = 0; i < col; i++)
{
for (int j = 0; j < row; xaxis++)
{
if (arr[i][j] == 'N')
{
count++;
}
}
}
if (count == col)
{
cout << "P2 wins!";
}
}
You can make the loop more efficient by terminating the loops after the first duplicate is found:
for (int i = 0; i < col; ++i)
{
for (int j = 0; j < row; ++j)
{
if (arr[i][j] == 'N')
{
++count;
if (count > 1)
{
break;
}
}
}
if (count > 1)
{
break;
}
}
The above code will terminate as soon as the first duplicate is found, thus not searching the entire board.

Puzzle related to sorting a 2-D array in ascending order

A randomly generated 4x4 2-D array is given to the user, of which one element is definitely 0. Considering 0 to be an empty location, the user will have to exchange the remaining 15 elements with 0 repeatedly until they get the array in ascending order, with 0 as the last element.
At this point, they're allowed to exchange any element with 0.
But how do I modify this code to ensure that are only able to exchange those elements with 0 that are adjacent to it (either above, below or beside it) ?
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
int check_asc(int a[][4])
{
int i, j, previous = a[0][0];
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
if(i == 3 && j == 3)
{
if (a[i][j] == 0)
return 1;
}
else if (a[i][j] < previous)
{
return 0;
}
previous = a[i][j];
}
}
return 1;
}
void swap(int a[][4], int &xpos, int &ypos)
{
int arr, temp;
cout << "\n\nEnter number to be swapped with 0: ";
cin >> arr;
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (a[i][j] == arr)
{
temp = a[xpos][ypos];
a[xpos][ypos] = a[i][j];
a[i][j] = temp;
xpos = i;
ypos = j;
return;
}
}
}
}
int check_rep(int a[][4], int assign)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (assign == a[i][j])
return 0;
}
}
return 1;
}
void main()
{
int a[4][4], assign, xpos = 0, ypos = 0, asc_result, rep_result;
srand((unsigned)time(NULL));
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
{
if (i == 0 && j == 0)
a[i][j] = 0;
else
{
do {
assign = rand() % 50;
rep_result = check_rep(a, assign);
} while (rep_result == 0);
a[i][j] = assign;
}
}
cout << "\n\nArrange the 4x4 matrix into ascending order. (Consider 0 as a blank space)" << endl;
for (int i = 0; i < 4; i++)
{
cout << endl;
for (int j = 0; j < 4; j++)
cout << a[i][j] << '\t';
}
do {
swap(a, xpos, ypos);
system("cls");
for (int i = 0; i < 4; i++)
{
cout << endl;
for (int j = 0; j < 4; j++)
cout << a[i][j] << '\t';
}
asc_result = check_asc(a);
} while (asc_result == 0);
cout << "\n\tYou win"<<endl;
system("pause");
}
Simple, just extend your swap function with a piece of code that will check whether the location of the element to be swapped is adjacent to the location of 0:
void swap(int a[][4], int &xpos, int &ypos)
{
...
if (a[i][j] == arr &&
((i == xpos && (j == ypos - 1 || j == ypos + 1)) ||
(j == ypos && (i == xpos - 1 || i == xpos + 1))))
{
temp = a[xpos][ypos];
a[xpos][ypos] = a[i][j];
a[i][j] = temp;
xpos = i;
ypos = j;
return;
}
An improvement would be to separate the check condition and inform the user in case when the element is not adjacent to 0.
Rough Algorithm
1) create a function find location, it will return a structure Point that has x, y integer fields, it will find the x, y location of any piece based on the pieces value, i.e. lets say 0 is entered, if it is located in the top left corner (0,0), a point (0, 0) will be returned
2) create a function that takes in 2 points, the location of the '0' and the location of the piece we wish to swap lets call it S, if S.x = 0.x and 0.y - 1 = S.y or S.y - 0.y + 1 then you know that said piece is directly above or below the 0, now of course you have ot add a few conditions for boundaries so as we dont check outside the grid. Have this function return an int 1 if the piece S is located above/below/beside, 0 if not.
3) if 1 is returned your allowed to do the flip, if 0 is returned find another piece

SUDOKU solver in c++

I need help to make a Sudoku solver in C++.
Requirements of the program:
Input Sudoku:[Done]
Read Sudoku: [Done]
Validate function: (validates the Sudoku:) [Done]
Display function [done]
solve function [need help]
My plan:
Make a function to validate the sudoku [done]
and assign possibility of 1-9 for every blank colume. and perform a brute-force
method to solve the puzzle. It will call the function validate each time
while doing brute force. It consumes a lot of time and I understood that it is
impossible.
I need a better algorithm for the solve function, please help me.
I have commented some of the code just to analyses the code: Apologize if that is the wrong way.
Here is what I have done so far:
/* Program: To solve a SU-DO-KU:
Date:23-sep-2013 # 5.30:
*/
#include<iostream>
using namespace std;
int su_in[9][9]={
0,0,7 ,0,0,0 ,4,0,6,
8,0,0 ,4,0,0 ,1,7,0,
0,0,0 ,3,0,0 ,9,0,5,
0,0,0 ,7,0,5 ,0,0,8,
0,0,0 ,0,0,0 ,0,0,0,
4,0,0 ,2,0,8 ,0,0,0,
7,0,4 ,0,0,3 ,0,0,0,
0,5,2 ,0,0,1 ,0,0,9,
1,0,8 ,0,0,0 ,6,0,0
};
int su_out[9][9];/*={
5,3,7 ,9,1,2 ,4,8,6,
8,2,9 ,4,5,6 ,1,7,3,
6,4,1 ,3,8,7 ,9,2,5,
9,1,3 ,7,4,5 ,2,6,8,
2,8,6 ,1,3,9 ,7,5,4,
4,7,5 ,2,6,8 ,3,9,1,
7,6,4 ,8,9,3 ,5,1,2,
3,5,2 ,6,7,1 ,8,4,9,
1,9,8 ,5,2,4 ,6,3,7
};*/
struct chance{
int poss[9];
};
int box_validate(int,int,int);
void read(int);
void display(int);
int validate(int);
int solve();
int main()
{
int i,j,row,get_res=2;
enum {input=1,output};
cout<<"enter the sudoku: use 0 if the colum is empty:\n";
// for(i=0; i<9; i++){
// read(i);
// }
cout<<"\n\t\tTHE ENTERED SU-DO-CU IS:\n\n";
display(input);
get_res=validate(input);
if(get_res==0)
cout<<"valid input!\n";
else if(get_res==1)
cout<<"invalid input!\n";
// display(input);
for(i=0; i<9; i++)
for(j=0; j<9; j++)
su_out[i][j]=su_in[i][j];
// display(output);
get_res=validate(output);
if(get_res==0){
cout<<"valid solution!\n"; display(output);}
// else if(get_res==1)
// cout<<"invalid sudoku!\n";
if(solve()==0) display(output);
else cout<<"not solved buddy!!\n";
}
void read(int row) // function to read the SU-DO-CU
{
unsigned num,i;
cout<<"enter the row:'"<<row+1<<"'\n";
for(i=0; i<9; i++)
{
cin>>num;
if(num<0||num>9)
cout<<"error! invalid input: enter a number < or = 9 and > or = 0 \n";
else
su_in[row][i]=num;
}
}
void display(int sudoku) // function to display the SU-DO-CU
{
unsigned i,j;
for(i=0;i<9; i++)
{
if(i%3==0)
cout<<"\t\t-------------------------\n";
cout<<"\t\t";
for(j=0; j<9; j++)
{
if(j%3==0)
cout<<"| ";
// if(su[i][j]==0)
// cout<<"_ ";
// else
if(sudoku==1)
cout<<su_in[i][j]<<" ";
else if(sudoku==2)
cout<<su_out[i][j]<<" ";
if(j==8)
cout<<"|";
}
cout<<"\n";
if(i==8)
cout<<"\t\t-------------------------\n";
}
}
int validate(int sudoku) // function to validate the input SU-DO-CU
{
unsigned i,j,k,n,count=0;
//..........................row validation
for(i=0; i<9; i++)
for(j=0; j<9; j++)
for(k=0;k<9;k++)
{
if(sudoku==1 && k!=j && su_in[i][j]!=0)
{
if(su_in[i][j]==su_in[i][k])
return 1;
}
else if(sudoku==2 && k!=j )
{
if(su_out[i][j]==su_out[i][k])
return 1;
}
}
//..................................colume validation
for(i=0; i<9; i++)
for(j=0; j<9; j++)
for(k=0; k<9; k++)
{
if(sudoku==1 && k!=j && su_in[j][i]!=0)
{
if(su_in[j][i]==su_in[k][i])
return 1;
}
else if(sudoku==2 && k!=i )
{
if(su_out[j][i]==su_out[j][k])
return 1;
}
}
// each box validating.......................
for(i=0; i<=6; i=i+3)
for(j=0; j<=6; j=j+3)
{
if(box_validate(i,j,sudoku)==1)
return 1;
}
// sum validation for output....
if(sudoku==2)
{
for(i=0; i<9; i++)
for(j=0; j<9; j++)
count=count+su_out[i][j];
if(count!=405) return 1;
}
return 0;
}
int box_validate(int i,int j,int sudoku)
{
unsigned k=j,n=i;
int temp_i=i,temp_j=j,temp_k=k, temp_n=n;
for(i=temp_i; i<temp_i+3; i++)
for(j=temp_j; j<temp_j+3; j++)
for(k=temp_k; k<temp_k+3; k++)
{
if(sudoku==1 && k!=j && su_in[i][j]!=0)
{
if(su_in[i][j]==su_in[i][k])
return 1;
for(n=temp_n; n<temp_n+3; n++)
{
if(sudoku==1 && su_in[i][j]!=0)
if(k==j && n==i)
;else
if(su_in[i][j]==su_in[n][k])
return 1;
}
}
if(sudoku==2 && k!=j )
{
if(su_out[i][j]==su_out[i][k])
return 1;
for(n=temp_n; n<temp_n+3; n++)
{
if(sudoku==1 )
if(k==j && n==i)
;else
if(su_out[i][j]==su_out[n][k])
return 1;
}
}
}
return 0;
}
int solve()
{
unsigned i,j,k,m,n,x;
struct chance cell[9][9];
for(i=0; i<9; i++)
for(j=0; j<9; j++)
if(su_in[i][j]==0)
for(k=0;k<9; k++)
cell[i][j].poss[k]=k+1;
/*
for(i=0; i<9; i++)
for(j=0; j<9; j++)
if(su_in[i][j]==0)
for(k=0;k<9; k++)
{ su_out[i][j]=cell[i][j].poss[k]=k+1;
su_out[i][j]=cell[i][j].poss[k];
for(m=0; m<9; m++)
for(n=0; n<9; n++)
for(x=1; x<=9; x++)
{ if(x!=k+1)
cell[m][n].poss[x]==x;
if(validate(2)==0)
return 0;
}
}*/
for(i=0; i<9; i++)
for(j=0; j<9; j++)
if(su_in[i][j]==0)
while (validate(2)==0)
{
for(k=0;k<9; k++)
{ su_out[i][j]=k+1;
for(m=i+1; m <9 ; m++)
for(n=0; n <9 ; n++)
for(x=1; x<=9; x++)
{ su_out[m][n]=x;
if(validate(2)==0)
return 0;
}
}
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define UNASSIGNED 0
#define N 9
bool FindUnassignedLocation(int grid[N][N], int &row, int &col);
bool isSafe(int grid[N][N], int row, int col, int num);
/* assign values to all unassigned locations for Sudoku solution
*/
bool SolveSudoku(int grid[N][N])
{
int row, col;
if (!FindUnassignedLocation(grid, row, col))
return true;
for (int num = 1; num <= 9; num++)
{
if (isSafe(grid, row, col, num))
{
grid[row][col] = num;
if (SolveSudoku(grid))
return true;
grid[row][col] = UNASSIGNED;
}
}
return false;
}
/* Searches the grid to find an entry that is still unassigned. */
bool FindUnassignedLocation(int grid[N][N], int &row, int &col)
{
for (row = 0; row < N; row++)
for (col = 0; col < N; col++)
if (grid[row][col] == UNASSIGNED)
return true;
return false;
}
/* Returns whether any assigned entry n the specified row matches
the given number. */
bool UsedInRow(int grid[N][N], int row, int num)
{
for (int col = 0; col < N; col++)
if (grid[row][col] == num)
return true;
return false;
}
/* Returns whether any assigned entry in the specified column matches
the given number. */
bool UsedInCol(int grid[N][N], int col, int num)
{
for (int row = 0; row < N; row++)
if (grid[row][col] == num)
return true;
return false;
}
/* Returns whether any assigned entry within the specified 3x3 box matches
the given number. */
bool UsedInBox(int grid[N][N], int boxStartRow, int boxStartCol, int num)
{
for (int row = 0; row < 3; row++)
for (int col = 0; col < 3; col++)
if (grid[row+boxStartRow][col+boxStartCol] == num)
return true;
return false;
}
/* Returns whether it will be legal to assign num to the given row,col location.
*/
bool isSafe(int grid[N][N], int row, int col, int num)
{
return !UsedInRow(grid, row, num) && !UsedInCol(grid, col, num) &&
!UsedInBox(grid, row - row % 3 , col - col % 3, num);
}
void printGrid(int grid[N][N])
{
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
cout<<grid[row][col]<<" ";
cout<<endl;
}
}
int main()
{
int grid[N][N] = {{3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0}};
if (SolveSudoku(grid) == true)
printGrid(grid);
else
cout<<"No solution exists"<<endl;
return 0;
}
Here's my code:
I think it's the best.
/*
* File: Sudoku-Solver.cc
*
* Created On: 12, April 2016
* Author: Shlomo Gottlieb
*
* Description: This program holds A sudoku board (size: 9*9),
* it allows the user to input values that he choices
* and finds the first rational solution.
* The program also prints the sudoku whether A solution
* was found or not.
*
*/
//========= Includes =========//
#include <iostream>
//========= Using ==========//
using namespace std;
//========= Constants =========//
const int N = 3; // The size of 1 square in the sudoku.
const int EMPTY = 0; // A sign for an empty cell.
const int STOP_INPUT = -1; // A sign for stop get input.
//====== Function Declaration ======//
void input_sud(int sud[][N*N]);
bool fill_sud(int sud[][N*N], int row, int col);
void print_sud(const int sud[][N*N]);
bool is_legal(const int sud[][N*N], int row, int col, int val);
bool is_row_ok(const int row[], int col, int val);
bool is_col_ok(const int sud[][N*N], int row, int col, int val);
bool is_sqr_ok(const int sud[][N*N], int row, int col, int val);
//========== Main ===========//
int main()
{
int sud[N*N][N*N] = { { EMPTY } }; // The sudoku board.
input_sud(sud);
fill_sud(sud, 0, 0);
print_sud(sud);
return 0;
}
//======== Input Sudoku ========//
// Gets the input for the sudoku,
// 0 means an empty cell.
void input_sud(int sud[][N*N])
{
for(int i = 0; i < N*N; i++)
for(int j = 0; j < N*N; j++)
cin >> sud[i][j];
}
//======== Fill Sudoku =========//
// Tries to fill-in the given sudoku board
// according to the sudoku rules.
// Returns whether it was possible to solve it or not.
bool fill_sud(int sud[][N*N], int row, int col)
{
// Points to the row number of the next cell.
int next_row = (col == N*N - 1) ? row + 1 : row;
// Points to the column number of the next cell.
int next_col = (col + 1) % (N*N);
// If we get here, it means we succeed to solve the sudoku.
if(row == N*N)
return true;
// Checks if we are allowed to change the value of the current cell.
// If we're not, then we're moving to the next one.
if(sud[row][col] != EMPTY)
return fill_sud(sud, next_row, next_col);
// We're about to try and find the legal and appropriate value
// to put in the current cell.
for(int value = 1; value <= N*N; value++)
{
sud[row][col] = value;
// Checks if 'value' can stay in the current cell,
// and returns true if it does.
if(is_legal(sud, row, col, value) && fill_sud(sud, next_row, next_col))
return true;
// Trial failed!
sud[row][col] = EMPTY;
}
// None of the values solved the sudoku.
return false;
}
//======== Print Sudoku ========//
// Prints the sudoku Graphically.
void print_sud(const int sud[][N*N])
{
for(int i = 0; i < N*N; i++)
{
for(int j = 0; j < N*N; j++)
cout << sud[i][j] << ' ';
cout << endl;
}
}
//========== Is Legal ==========//
// Checks and returns whether it's legal
// to put 'val' in A specific cell.
bool is_legal(const int sud[][N*N], int row, int col, int val)
{
return (is_row_ok(sud[row], col, val) &&
is_col_ok(sud, row, col, val) &&
is_sqr_ok(sud, row, col, val));
}
//========= Is Row OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific row.
bool is_row_ok(const int row[], int col, int val)
{
for(int i = 0; i < N*N; i++)
if(i != col && row[i] == val)
return false; // Found the same value again!
return true;
}
//========= Is Column OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific column.
bool is_col_ok(const int sud[][N*N], int row, int col, int val)
{
for(int i = 0; i < N*N; i++)
if(i != row && sud[i][col] == val)
return false; // Found the same value again!
return true;
}
//========= Is Square OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific square.
bool is_sqr_ok(const int sud[][N*N], int row, int col, int val)
{
int row_corner = (row / N) * N;
// Holds the row number of the current square corner cell.
int col_corner = (col / N) * N;
// Holds the column number of the current square corner cell.
for(int i = row_corner; i < (row_corner + N); i++)
for(int j = col_corner; j < (col_corner + N); j++)
if((i != row || j != col) && sud[i][j] == val)
return false; // Found the same value again!
return true;
}
//here's a pseudo sudoku solver:
#include <iostream>
#include <cmath>
#include "time.h"
//for(int i=0; i< ++i){}
using namespace std;
int main(){
int a[9][9]={{0,7,0,0,2,0,1,0,0},
{6,0,3,0,0,0,0,0,0},
{2,0,0,3,0,0,5,0,0},
{0,0,0,0,3,0,0,6,0},
{0,6,4,7,0,0,0,8,0},
{0,5,0,0,9,0,0,4,0},
/*54*/ {0,4,0,0,7,0,9,0,0},
{0,2,0,0,0,8,0,5,0},
{0,0,0,0,0,0,0,0,0}};/*this is the grid. I need to use two so that I can use one as a constant reference*/
int a2[9][9]={{0,7,0,0,2,0,1,0,0},
{6,0,3,0,0,0,0,0,0},
{2,0,0,3,0,0,5,0,0},
{0,0,0,0,3,0,0,6,0},
{0,6,4,7,0,0,0,8,0},
{0,5,0,0,9,0,0,4,0},
{0,4,0,0,7,0,9,0,0},
{0,2,0,0,0,8,0,5,0},
{0,0,0,0,0,0,0,0,0}};
int x=0,y=0,z=0;
int oo=0,o=0,ooo=0,oooo=0;
for(int i=0; i<9; ++i)/*this is the double for loop. to keep track of the cells*/
{
for(int j=0; j<9; ++j)
{
if(!a2[i][j])
{a://label that if something doesn't work, to restart here.
++a[i][j];//increment the number in the cell by 1.
if(a[i][j]>9)/*if no valid number is found/the number is out of range, execute the if statement. **This is the backtracking algorithm.***/
{
a[i][j]=0;//erase the invalid number.
--j;if(j<0){--i;j=8;} /*if j equals < 0, j is reset to 8, as the first 9 numbers are easy to find, and if j needs to be reset, there will always be a number in the j equals 8 cell. The "i" will never be less than zero, if it is a valid puzzle, so the j=8 will only happen after i is > 0.*/
while(a2[i][j]){--j;if(j<0){--i;j=8;}}/*if there was a number present from the beginning, skip it until a variable cell space is found.*/
goto a;//jump to a: and increment the current number in the cell by 1.
}
if(j<3){o=0;oo=3;}if(j>2 && j<6){o=3;oo=6;}/*locate the 3X9 grid j is in.*/
if(j>5){o=6;oo=9;}
if(i<3){ooo=0;oooo=3;}if(i>2 && i<6){ooo=3;oooo=6;}/*locate the 9X3 grid i is in.*/
if(i>5){ooo=6;oooo=9;}
for(int u=ooo; u<oooo; ++u)/*intersect the 3X9 and 9X3 grids to create a searchable 3X3 grid.*/
{
for(int p=o; p<oo; ++p)
{
if(a[u][p]==a[i][j]){++x;if(x>1){x=0;goto a;}}/*if the number is not valid, go to a: and increment the number in the cell by 1.*/
}
}
x=0;
for(int n=0; n<9; ++n)
{
if(a[i][j]==a[i][n]){++y; if(y>1){y=0;goto a;}}/*if no valid number is found, goto a: and increment the number in the cell by 1.*/
}y=0;
for(int m=0; m<9; ++m)
{
if(a[i][j]==a[m][j]){++y; if(y>1){y=0;goto a;}}//""
} y=0;
}
}
}
for(int i=0; i<9; ++i)//print the completed puzzle.
{
for(int j=0; j<9; ++j)
{
cout<<a[i][j]<<" ";
}
cout<<endl;//print on the next line after 9 digits are printed.
}
return 0;
}
//if no valid puzzle is found, the screen hangs. - Harjinder
/*random sudokus' can be generated and solved in one program by copying the following code into an editor. hit enter to generate and solve a new puzzle:
//the following works the same way as above except that it is 2 solvers in a continuous while loop
//the first solver, to generate the random puzzle:
#include <iostream>
using namespace std;
int main(){
while(1){
int a[9][9]={0}, a2[9][9]={0};
int w=0, x=0,y=0,z=0, yy=0, oo=0,o=0,ooo=0,oooo=0;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
if(!a2[i][j])
{srand(time(0));if(w<5){++w;a[i][j]=rand()%9;}a:++a[i][j];//generate a random number from 0 to 9 and and then increment by 1.
if(a[i][j]>9)
{
a[i][j]=0;
--j;if(j<0){--i;j=8;}
while(a2[i][j]){--j;if(j<0){--i;j=8;}}
goto a;
}
if(j<3){o=0;oo=3;}if(j>2 && j<6){o=3;oo=6;}
if(j>5){o=6;oo=9;}
if(i<3){ooo=0;oooo=3;}if(i>2 && i<6){ooo=3;oooo=6;}
if(i>5){ooo=6;oooo=9;}
for(int u=ooo; u<oooo; ++u)
{
for(int p=o; p<oo; ++p)
{
if(a[u][p]==a[i][j]){++x;if(x>1){x=0;goto a;}}
}}
x=0;
for(int n=0; n<9; ++n)
{
if(a[i][j]==a[i][n]){++y; if(y>1){y=0;goto a;}}
}y=0;
for(int m=0; m<9; ++m)
{
if(a[i][j]==a[m][j]){++y; if(y>1){y=0;goto a;}}
} y=0;}//if
}
}
//the second part below is to add zeros' to the puzzle, and copy the puzzle into the second solver arrays.
int n=40;//adjusts the amount of empty spaces. works only if landed on non-zero, or else the zero will be counted.
x=0;int xx=0;
o=0;int pp=0,ppp=0;
while(o<n)
{
pp=rand()%9;
ppp=rand()%9;
a[pp][ppp]=0;
pp=rand()%9;
ppp=rand()%9;
a[ppp][pp]=0;
++o;
}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
x=0,xx=0;
cout<<endl<<endl;
int a5[9][9]={0}, a6[9][9]={0};x=-1;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
++x;
a5[i][j]=a[i][j];//copy first puzzle with added zeros into the new array.
}
}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
a6[i][j]=a5[i][j];//copy the updated puzzle with zeros, into the constant reference array.
}
}
x=0;
////////////////////////////////////////////////////////////////////////
//second solver to solve the zero updated array:
cout<<endl<<endl;
o=0;
y=0,z=0;
oo=0,ooo=0,oooo=0;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
if(!a6[i][j])
{c5:
++a5[i][j];
if(a5[i][j]>9)
{
a5[i][j]=0;
--j;if(j<0){--i;j=8;}
while(a6[i][j]){--j;if(j<0){--i;j=8;}}
goto c5;
}
if(j<3){o=0;oo=3;}if(j>2 && j<6){o=3;oo=6;}
if(j>5){o=6;oo=9;}
if(i<3){ooo=0;oooo=3;}if(i>2 && i<6){ooo=3;oooo=6;}
if(i>5){ooo=6;oooo=9;}
for(int u=ooo; u<oooo; ++u)
{
for(int p=o; p<oo; ++p)
{
if(a5[u][p]==a5[i][j]){++x;if(x>1){x=0;goto c5;}}
}}
x=0;
for(int n=0; n<9; ++n)
{
if(a5[i][j]==a5[i][n]){++y; if(y>1){y=0;goto c5;}}
}y=0;
for(int m=0; m<9; ++m)
{
if(a5[i][j]==a5[m][j]){++y; if(y>1){y=0;goto c5;}}
} y=0;} }
}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
cout<<a5[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
system("pause");//hit enter to load a new puzzle
}
return 0;
} */
The answer given above is similar to what a lot of people have posted at several websites like https://www.geeksforgeeks.org/sudoku-backtracking-7/. TBH, those solutions are not intuitive to me when they don't initialize row and col and call it in the FindUnassignedLocation function. I wanted to give it a shot myself with slight help from another answer I found on LeetCode. If it helps anyone, here you go.
// https://www.pramp.com/challenge/O5PGrqGEyKtq9wpgw6XP
#include <iostream>
#include <vector>
using namespace std;
// Print the sudoku
void print(vector<vector<char>> board){
for(int i = 0; i < board.size(); i++){
for(int j = 0; j < board[i].size(); j++){
cout << board[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
// Check if sudoku is all filled up
bool checkIfFilled(vector<vector<char>> board){
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
if(board[i][j] == '.')
return false;
}
}
return true;
}
// Check if a given number can be inserted at a given position
bool checkIfInsertOkay(vector<vector<char>> board, int x, int y, char num){
// Check row if num already exists
for(int j = 0; j < 9; j++){
if(board[x][j] == num)
return false;
}
// Check column if num already exists
for(int i = 0; i < 9; i++){
if(board[i][y] == num)
return false;
}
// Check 3x3 gird if num already exists
// Find the corners
// Find i
if(x < 3)
x = 0;
else if(x < 6)
x = 3;
else
x = 6;
// Find j
if(y < 3)
y = 0;
else if(y < 6)
y = 3;
else
y = 6;
// Check the 3x3 box
for(int i = x; i < x+3; i++){
for(int j = y; j < y+3; j++){
if(board[i][j] == num)
return false;
}
}
return true;
}
// Helper function because of const issues
bool sudokuSolveHelper(vector<vector<char>> &board){
// Base condition - if sudoku gets completely filled
if(checkIfFilled(board))
return true;
// Iterate through the sudoku
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
// If empty space
if(board[i][j] == '.'){
for(int k = 1; k <= 9; k++){
// Check if char(k) can be inserted at this empty location
char ch = '0' + k;
if(checkIfInsertOkay(board, i, j, ch)){
// Put k in this empty location and check
board[i][j] = ch;
// Check if done
bool flag = sudokuSolveHelper(board);
if(flag)
return true;
else
// Else, backtrack by making it empty again
board[i][j] = '.';
}
}
return false;
}
}
}
return true;
}
// Return true if a correct sudoku can be formed
// Apply backtracking
// Time complexity = O(9^empty spaces)
bool sudokuSolve(vector<vector<char>> &board){
return sudokuSolveHelper(board);
}
int main() {
vector<vector<char>> board = {
{'.','.','.','7','.','.','3','.','1'},
{'3','.','.','9','.','.','.','.','.'},
{'.','4','.','3','1','.','2','.','.'},
{'.','6','.','4','.','.','5','.','.'},
{'.','.','.','.','.','.','.','.','.'},
{'.','.','1','.','.','8','.','4','.'},
{'.','.','6','.','2','1','.','5','.'},
{'.','.','.','.','.','9','.','.','8'},
{'8','.','5','.','.','4','.','.','.'}
};
print(board);
bool flag = sudokuSolve(board);
if(flag){
cout << "A solution exists as below\n";
print(board);
}
else
cout << "No solution exists!\n";
return 0;
}
//the following works like the one above accept there is a while loop instead of goto statements:
#include <iostream>
#include <cmath>
#include "time.h"
//for(int i=0; i< ++i){}
using namespace std;
int main(){
int a[9][9]={{2,0,0,0,0,0,0,0,1},
{0,0,0,9,0,6,0,0,0},
{0,0,0,8,0,1,7,2,0},
{9,0,0,3,0,0,0,0,0},
{0,0,8,0,0,0,2,0,4},
{0,0,0,0,0,0,0,1,3},
/*54*/ {1,0,3,0,0,5,0,0,9},
{0,0,0,0,0,0,0,0,0},
{0,4,6,2,0,0,0,0,0}};
int a2[9][9]={{2,0,0,0,0,0,0,0,1},
{0,0,0,9,0,6,0,0,0},
{0,0,0,8,0,1,7,2,0},
{9,0,0,3,0,0,0,0,0},
{0,0,8,0,0,0,2,0,4},
{0,0,0,0,0,0,0,1,3},
{1,0,3,0,0,5,0,0,9},
{0,0,0,0,0,0,0,0,0},
{0,4,6,2,0,0,0,0,0}};
int x=0,y=0,z=0;
int colPlusThree=0,col=0,row=0,rowPlusThree=0;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{z=0;
if(!a2[i][j])
{while(z==0){ //the master while loop. loops until a valid number is found.
++a[i][j];
if(a[i][j]>9)
{
a[i][j]=0;
--j;if(j<0){--i;j=8;}
while(a2[i][j]){--j;if(j<0){--i;j=8;}}
++a[i][j];if(a[i][j]>9){--j;}
}
if(j<3){col=0;colPlusThree=3;}if(j>2 && j<6){col=3;colPlusThree=6;}
if(j>5){col=6;colPlusThree=9;}
if(i<3){row=0;rowPlusThree=3;}if(i>2 && i<6){row=3;rowPlusThree=6;}
if(i>5){row=6;rowPlusThree=9;}
for(int u=row; u<rowPlusThree; ++u)
{
for(int p=col; p<colPlusThree; ++p)
{
if(a[u][p]==a[i][j]){++x;if(x>1){u=rowPlusThree;break;}}
}}if(x<2){z=1;}else{z=0;}x=0;
for(int n=0; n<9; ++n)
{
if(z==0){y=2;break;}
if(a[i][j]==a[i][n]){++y; if(y>1){break;}}
}if(y<2){z=1;}else{z=0;}y=0;
for(int m=0; m<9; ++m)
{
if(z==0){y=2;break;}
if(a[i][j]==a[m][j]){++y; if(y>1){break;}}
} if(y<2){z=1;}else{z=0;}y=0;}}}}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}// - Harjinder