Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
aadityakhare authored Oct 17, 2017
1 parent a4bba8d commit a79accf
Show file tree
Hide file tree
Showing 90 changed files with 6,375 additions and 0 deletions.
106 changes: 106 additions & 0 deletions backtracking/knightsTour/C++/knightsTour.cpp
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;
}
9 changes: 9 additions & 0 deletions backtracking/knightsTour/README.md
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
![Open Knight's Tour example](https://upload.wikimedia.org/wikipedia/commons/d/da/Knight%27s_tour_anim_2.gif)
[Source](https://en.wikipedia.org/wiki/Knight%27s_tour)

#### Reference:
[Wikipedia](https://en.wikipedia.org/wiki/Knight%27s_tour)
66 changes: 66 additions & 0 deletions backtracking/rat_in_a_maze/cpp/rat_in_a_maze.cpp
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;
}
5 changes: 5 additions & 0 deletions backtracking/sudoku/README.md
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
![](sudoku.png)
131 changes: 131 additions & 0 deletions backtracking/sudoku/c++/sudoku.c++
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;
}
Loading

0 comments on commit a79accf

Please sign in to comment.