-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a4bba8d
commit a79accf
Showing
90 changed files
with
6,375 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
#include <iostream> | ||
#include <vector> | ||
using std::vector; | ||
|
||
class knightsTour{ | ||
vector< vector<int> > board; | ||
int sizeX; | ||
int sizeY; | ||
bool complete; | ||
unsigned long long numMoves; | ||
public: | ||
knightsTour(const int& sizeX, const int& sizeY, const int& startX, const int& startY){ | ||
for (size_t i = 0; i < sizeY; i++) { | ||
vector<int> v; | ||
for (size_t j = 0; j < sizeX; j++) { | ||
v.push_back(0); | ||
} | ||
board.push_back(v); | ||
} | ||
this->complete = false; | ||
this->sizeX = sizeX; | ||
this->sizeY = sizeY; | ||
traverse(startX, startY); | ||
} | ||
void traverse(const int& currentX, const int& currentY, const int& count=1); | ||
void printBoard(); | ||
}; | ||
|
||
void knightsTour::traverse(const int& currentX, const int& currentY, const int& count){ | ||
// Base cases: stopping conditions for recursion | ||
|
||
// Already completed traversal for this instance from it's starting point | ||
if(complete) return; | ||
|
||
// Illegal positions (out of range) | ||
if((currentX<0)||(currentY<0)) return; | ||
if((currentX>=sizeX)||(currentY>=sizeY)) return; | ||
|
||
// This position has already been tried | ||
if(board[currentY][currentX]>0){ | ||
return; | ||
} | ||
else{ | ||
// Set board to this count | ||
board[currentY][currentX]=count; | ||
numMoves++; | ||
|
||
// If count is the square of the size, this is the last square nessesary | ||
// to complete the knight's tour so complete is set to true | ||
if (count==(sizeX*sizeY)) { | ||
complete=true; | ||
return; | ||
} | ||
|
||
// If not completed, try all possible moves for the knight | ||
// (any of the 8 possible L moves) with the next count | ||
int c=count+1; | ||
traverse(currentX+2,currentY+1,c); | ||
traverse(currentX+2,currentY-1,c); | ||
traverse(currentX+1,currentY-2,c); | ||
traverse(currentX-1,currentY-2,c); | ||
traverse(currentX-2,currentY-1,c); | ||
traverse(currentX-2,currentY+1,c); | ||
traverse(currentX-1,currentY+2,c); | ||
traverse(currentX+1,currentY+2,c); | ||
|
||
// The above code explores to the full depth of each option from this point. | ||
// If all possible moves are explored and none have lead to a completed tour | ||
// then this is not the correct move from its parent state so go back up | ||
// and try a different move. | ||
if(!complete){ | ||
board[currentY][currentX]=0; | ||
if (count==1){ | ||
std::cout << "Tour of "<< sizeX << " by " << sizeY; | ||
std::cout <<" not found through any combination.\nNot possible to have a knights tour from this start position"<< std::endl; | ||
} | ||
return; | ||
} | ||
|
||
// If it is complete and it has reached up to the first state then print | ||
// out the board with the ordering filled in. | ||
if((complete)&&(count==1)){ | ||
printBoard(); | ||
std::cout << "Tour of "<< sizeX << " by " << sizeY; | ||
std::cout <<" board complete in "<< numMoves <<" moves!"<< std::endl; | ||
} | ||
} | ||
} | ||
|
||
void knightsTour::printBoard(){ | ||
for (size_t i = 0; i < sizeY; i++) { | ||
for (size_t j = 0; j < sizeX; j++) { | ||
std::cout<<board[i][j]<<"\t"; | ||
} | ||
std::cout<<"\n"; | ||
} | ||
} | ||
|
||
int main(){ | ||
int sizeX = 5; | ||
int sizeY = 5; | ||
int startX = 2; | ||
int startY = 2; | ||
knightsTour k(sizeX, sizeY, startX, startY); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
### KnightsTour using backtracking | ||
A knights tour is a sequence of L-shaped knight moves on an m by n chessboard such that, following the sequence, a knight visits each square exactly once. If the sequence ends with the knight returning to its starting position, the tour is called closed. The problem of finding a knights tour is an instance of the more general NP-Complete hamiltonian path problem. While the knights tour problem can be solved in linear time, the implementation here uses backtracking and is significantly slower. In this implementation, each of 8 possible moves are tried at each level of the recursive tree. If at any point the algorithm finds a dead end in the sequence of moves it is currently exploring, it undoes the current move and continues to exhaust all moves from the earlier steps. The algorithm continues trying all of these moves in a brute force way until it either reaches a depth of m+n in the recursive tree and has covered squares on the board or has tried all possible moves. | ||
|
||
#### A graphical example of Sudoku using backtracking | ||
 | ||
[Source](https://en.wikipedia.org/wiki/Knight%27s_tour) | ||
|
||
#### Reference: | ||
[Wikipedia](https://en.wikipedia.org/wiki/Knight%27s_tour) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
|
||
#include <iostream> | ||
#define N 9 | ||
using namespace std; | ||
|
||
int maze[N][N]; | ||
int path[N][N] = {0}; | ||
int direction[4][2] = { {0,1}, {1,0}, {0,-1}, {-1,0} }; | ||
int src_x, src_y, dest_x, dest_y; | ||
|
||
bool is_valid_move (int x, int y) { | ||
return (x >= 0 && x < N && y >= 0 && y < N && maze[x][y] == 0); | ||
} | ||
|
||
// this will not give the shortest path but only give one of the possible paths | ||
|
||
bool traverse (int curr_x, int curr_y) { | ||
if (curr_x == dest_x && curr_y == dest_y) | ||
return true; | ||
for (int k = 0; k < 4; k++) { | ||
int next_x = curr_x + direction[k][0]; | ||
int next_y = curr_y + direction[k][1]; | ||
if (is_valid_move (next_x, next_y)) { | ||
maze[curr_x][curr_y] = 1; // as the rat has already traversed this path marking it as a block to prevent rat from moving backwards | ||
path[next_x][next_y] = 1; | ||
if (traverse (next_x, next_y) == true) | ||
return true; | ||
else { | ||
maze[curr_x][curr_y] = 0; | ||
path[next_y][next_y] = 0; | ||
} | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
int main() { | ||
cout << "Enter the maze (0 for empty, 1 for blocked square, 5 for source and 6 for destination) : \n"; | ||
for (int i = 0; i < N; i++) { | ||
for (int j = 0; j < N; j++) { | ||
cin >> maze[i][j]; | ||
if (maze[i][j] == 5) { | ||
src_x = i; | ||
src_y = j; | ||
} | ||
if (maze[i][j] == 6) { | ||
dest_x = i; | ||
dest_y = j; | ||
} | ||
} | ||
} | ||
path[src_x][src_y] = 1; | ||
maze[src_x][src_y] = 0; | ||
maze[dest_x][dest_y] = 0; | ||
if (! traverse (src_x, src_y)) { | ||
cout << "Sorry! The rat cannot reach the destination..."; | ||
return 0; | ||
} | ||
cout << "The path followed by the rat to reach the destination is : \n"; | ||
for (int i = 0; i < N; i++) { | ||
for (int j = 0; j < N; j++) | ||
cout << path[i][j] << " "; | ||
cout << endl; | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
### Sudoku using backtracking | ||
Like all other Backtracking problems, we can solve Sudoku by one by one assigning numbers to empty cells. Before assigning a number, we check whether it is safe to assign. We basically check that the same number is not present in current row, current column and current 3X3 subgrid. After checking for safety, we assign the number, and recursively check whether this assignment leads to a solution or not. If the assignment doesn’t lead to a solution, then we try next number for current empty cell. And if none of number (1 to 9) lead to solution, we return false. | ||
|
||
#### A graphical example of Sudoku using backtracking | ||
 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include <stdio.h> | ||
|
||
// UNASSIGNED is used for empty cells in sudoku grid | ||
#define UNASSIGNED 0 | ||
|
||
// N is used for size of Sudoku grid. Size will be NxN | ||
#define N 9 | ||
|
||
// This function finds an entry in grid that is still unassigned | ||
bool FindUnassignedLocation(int grid[N][N], int &row, int &col); | ||
|
||
// Checks whether it will be legal to assign num to the given row,col | ||
bool isSafe(int grid[N][N], int row, int col, int num); | ||
|
||
/* Takes a partially filled-in grid and attempts to assign values to | ||
all unassigned locations in such a way to meet the requirements | ||
for Sudoku solution (non-duplication across rows, columns, and boxes) */ | ||
bool SolveSudoku(int grid[N][N]) | ||
{ | ||
int row, col; | ||
|
||
// If there is no unassigned location, we are done | ||
if (!FindUnassignedLocation(grid, row, col)) | ||
return true; // success! | ||
|
||
// consider digits 1 to 9 | ||
for (int num = 1; num <= 9; num++) | ||
{ | ||
// if looks promising | ||
if (isSafe(grid, row, col, num)) | ||
{ | ||
// make tentative assignment | ||
grid[row][col] = num; | ||
|
||
// return, if success, yay! | ||
if (SolveSudoku(grid)) | ||
return true; | ||
|
||
// failure, unmake & try again | ||
grid[row][col] = UNASSIGNED; | ||
} | ||
} | ||
return false; // this triggers backtracking | ||
} | ||
|
||
/* Searches the grid to find an entry that is still unassigned. If | ||
found, the reference parameters row, col will be set the location | ||
that is unassigned, and true is returned. If no unassigned entries | ||
remain, false is returned. */ | ||
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 a boolean which indicates whether any assigned entry | ||
in 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 a boolean which indicates 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 a boolean which indicates 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 a boolean which indicates 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) | ||
{ | ||
/* Check if 'num' is not already placed in current row, | ||
current column and current 3x3 box */ | ||
return !UsedInRow(grid, row, num) && | ||
!UsedInCol(grid, col, num) && | ||
!UsedInBox(grid, row - row%3 , col - col%3, num); | ||
} | ||
|
||
/* A utility function to print grid */ | ||
void printGrid(int grid[N][N]) | ||
{ | ||
for (int row = 0; row < N; row++) | ||
{ | ||
for (int col = 0; col < N; col++) | ||
printf("%2d", grid[row][col]); | ||
printf("\n"); | ||
} | ||
} | ||
|
||
// Test program | ||
int main() | ||
{ | ||
// 0 means unassigned cells | ||
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 | ||
printf("No solution exists"); | ||
|
||
return 0; | ||
} |
Oops, something went wrong.