I am trying to solve Knight Tour Problem using recursive Backtracking. Can someone help me optimize my code. My code works till 6X6 board. . After N=7 it takes almost infinite time to solve .
Here is my code :
#include <iostream>
#include "genlib.h"
#include "grid.h"
#include "vector.h"
#include <iomanip>
const int NOT_VISITED = -1;
//Size of the board
const int N = 6;
const int N2 = N*N;
typedef Grid<int> chess;
struct position{
int row;
int col;
};
//Initializes the board and makes each and every
//square value as NOT_VISITED
void initializeBoard(chess &board)
{
for(int i=0;i<board.numRows();i++)
for(int j=0;j<board.numCols();j++)
board[i][j] = NOT_VISITED;
}
//Returns true if the square is visited;
bool visited(chess &board,position square)
{
return board[square.row][square.col ] != NOT_VISITED;
}
//Returns true if the givien position variable is outside the chess board
bool outsideChess(chess &board, position square)
{
if(square.row <board.numRows() && square.col <board.numCols() && square.row >=0 && square.col >=0)
return false;
return true;
}
void visitSquare(chess &board,position square,int count)
{
board[square.row] [square.col] = count;
}
void unVisitSquare(chess &board,position square)
{
board[square.row] [square.col] = NOT_VISITED;
}
position next(position square,int irow, int icol)
{
square.row += irow;
square.col += icol;
return square;
}
Vector<position> calulateNextSquare(chess board,position square)
{
Vector<position> list;
for(int i=-2;i<3;i=i+4)
{
for(int j=-1;j<2;j=j+2)
{
list.add(next(square,i,j));
list.add(next(square,j,i));
}
}
return list;
}
bool knightTour(chess &board,position square, int count)
{
//cout<<count<<endl;
//Base Case if the problem is solved;
if(count>N2)
return true;
if(outsideChess(board,square))
return false;
//return false if the square is already visited
if(visited(board,square))
return false;
visitSquare(board,square,count);
Vector<position> nextSquareList = calulateNextSquare(board,square);
for(int i=0;i<nextSquareList.size();i++)
if(knightTour(board, nextSquareList[i], count+1))
return true;
unVisitSquare(board,square);
return false;
}
void printChess(chess &board)
{
for(int i=0;i<board.numRows();i++)
{
for(int j=0;j<board.numCols();j++)
cout<<setw(4)<<board[i][j];
cout<<endl;
}
}
int main()
{
chess board(N,N);
initializeBoard(board);
position start;
start.row = 0; start.col = 0;
if(knightTour(board,start,1))
printChess(board);
else
cout<<"Not Possible";
return 0;
}
i am using Stanford 106B Libraries( grid is a 2 dimensional vector )
Visual studio 2008 Blank project with required library files https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0BwLe9NJT8IreNWU0N2M5MGUtY2UxZC00ZTY2LWE1YjQtMjgxYzAxMWE3OWU2&hl=en
I'd say, for a start, get rid of this:
Vector<position> nextSquareList = calulateNextSquare(board,square);
creating a Vector on each step will take a lot of time. You could either use an array (fixed sized, since you know there are 8 possible moves), or unroll the loop entirely. Compare with this version, similar to yours.
Some modifications I would like to suggest:
#include <iostream>
#include "genlib.h"
#include "grid.h"
#include "vector.h"
#include <iomanip>
const int NOT_VISITED = -1;
//Size of the board
const int N = 6;
const int N2 = N*N;
typedef int chess[N][N]; // <------------- HERE
struct position{
int row;
int col;
};
//Initializes the board and makes each and every
//square value as NOT_VISITED
void initializeBoard(chess &board)
{
for(int i=0;i<board.numRows();i++)
for(int j=0;j<board.numCols();j++)
board[i][j] = NOT_VISITED;
}
//Returns true if the square is visited;
bool visited(chess &board,position square)
{
return board[square.row][square.col ] != NOT_VISITED;
}
//Returns true if the givien position variable is outside the chess board
bool outsideChess(chess &board, position square)
{
if(square.row <board.numRows() && square.col <board.numCols() && square.row >=0 && square.col >=0)
return false;
return true;
}
void visitSquare(chess &board,position square,int count)
{
board[square.row] [square.col] = count;
}
void unVisitSquare(chess &board,position square)
{
board[square.row] [square.col] = NOT_VISITED;
}
position next(position square,int irow, int icol)
{
square.row += irow;
square.col += icol;
return square;
}
void calulateNextSquare(chess board,position square, Vector<position>& list) // <------------- HERE
{
// ------------- HERE
//Also, change this part to add only unvisited and not out-of-board positions.
for(int i=-2;i<3;i=i+4)
{
for(int j=-1;j<2;j=j+2)
{
list.add(next(square,i,j));
list.add(next(square,j,i));
}
}
}
bool knightTour(chess &board,position square, int count)
{
//cout<<count<<endl;
//Base Case if the problem is solved;
if(count>N2)
return true;
if(outsideChess(board,square))
return false;
//return false if the square is already visited
if(visited(board,square))
return false;
visitSquare(board,square,count);
Vector<position> nextSquareList; // <------------- HERE
calulateNextSquare(board,square,nextSquareList);
for(int i=0;i<nextSquareList.size();i++)
if(knightTour(board, nextSquareList[i], count+1))
return true;
unVisitSquare(board,square);
return false;
}
void printChess(chess &board)
{
for(int i=0;i<board.numRows();i++)
{
for(int j=0;j<board.numCols();j++)
cout<<setw(4)<<board[i][j];
cout<<endl;
}
}
int main()
{
chess board(N,N);
initializeBoard(board);
position start;
start.row = 0; start.col = 0;
if(knightTour(board,start,1))
printChess(board);
else
cout<<"Not Possible";
return 0;
}
But please note that you still have a exponential complexity, and optimizing your code wont change it.
You are passing a copy of the board to calculateNextSquare but it seems you don't need it in this method.
Also, you return a vector in this method but you should pass it by reference.
Related
I am trying to create a map where you as a player can move through the map using up,down,left & right keys and so far im in the right path. What bothers me is that everytime I reach an element outside its vector scope it errors me out saying
vector subscript out of range
and I know what this means so I'm figuring out a solution to solve this but how am I supposed to do this? Making an if statement telling that if it reaches a certain element it should not increment the value of moveY and just return false
This code below me does not work.. :/
bool Map::Player_Pos(float posY, float posX)
{
this->map[posY][posX] = '#';
if (GetAsyncKeyState(0x28))
{
if (moveY == 10)
{
return false;
}
this->map[posY][posX] = '.';
moveY += 1;
}
return true;
}
The problem lies at bool Player_Pos(float posY, float posX); so any suggestions would be really appreciated!
#include <iostream>
#include <vector>
#include <Windows.h>
class Map
{
private:
float moveY = 0.f;
float moveX = 0.f;
std::vector<std::vector<char>> map;
public:
Map(int dim1, int dim2, char type)
{
map.resize(dim1, std::vector<char>(dim2, type));
}
bool Update()
{
system("cls");
for (int i = 0; i < map.size(); i++)
{
for (int j = 0; j < map.size(); j++)
{
std::cout << map[i][j];
}
std::cout << '\n';
}
return true;
}
bool Player_Pos(float posY, float posX);
float posY() { return moveY; }
float posX() { return moveX; }
};
bool Map::Player_Pos(float posY, float posX)
{
this->map[posY][posX] = '#';
if (GetAsyncKeyState(0x28))
{
if (moveY == 10) // This does not work! Still keeps going and crashes compiler
{
return false;
}
this->map[posY][posX] = '.';
moveY += 1;
}
return true;
}
int main()
{
Map map = Map(10, 10, '.');
while (true)
{
map.Player_Pos(map.posY(), map.posX()); // Initialize position
map.Update(); // Update map
}
return 0;
}
I am making a directed Graph class. I want find if there is any Cycle and update a vector with it's path accordingly. My Function some times work but others add two times the last edge of the path.So i guess it needs to be tydied up.
Example: having a Graph with these paths
0->1, 0->2, 1->2, 2->3, 3->4, 4->0, 4->6, 1->5, 5->6
should set the vector to [0 2 3 4] or anything else valid.
What I have tried:
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
class Graph {
private:
int V;
list<int> *adj;
bool isCyclicHelp(int v, bool visited[], bool *rs, vector<int> &path) const{
if(visited[v] == false) {
visited[v] = true;
rs[v] = true;
list<int>::iterator i;
for(i=adj[v].begin(); i!=adj[v].end(); i++) {
if(!visited[*i] && isCyclicHelp(*i, visited, rs, path)) {
path.push_back(*i);
return true;
}
else if(rs[*i]) {
return true;
}
}
}
rs[v] = false;
path.pop_back();
return false;
}
public:
Graph(int V) {
this->V = V;
adj = new list<int>[V];
}
~Graph() {
}
void addEdge(int v, int w) {
if(v != w) {
adj[v].push_back(w);
}
}
bool cycle(vector<int> &path) const {
bool *visited = new bool[V];
bool *recStack = new bool[V];
for(int i=0; i<V; i++) {
visited[i] = false;
recStack[i] = false;
}
for(int i=0; i<V; i++) {
path.push_back(i);
if(Graph::isCyclicHelp(i, visited, recStack, path)) {
reverse(path.begin(), path.end());
return true;
}
path.clear();
}
path.clear();
return false;
}
};
in my C++ class we are finally getting conceptually fairly deep (well, relatively!) and I'm struggling with building a class from a previous class.
Here is my first class header, which builds partially filled array objects. To my knowledge, it is fully functional:
#ifndef PARTIALARRAY_H
#define PARTIALARRAY_H
#include <iostream>
#include <string.h>
using namespace std;
typedef int ITEM_TYPE;
ITEM_TYPE const MAX = 50;
class PartialArray
{
public:
//-----------------------------------------ctors:-----------------------------------------
PartialArray();
PartialArray(const int init[], int used);
//-----------------------------------------member functions:-----------------------------------------
void PrintArray();
int Search(ITEM_TYPE key);
int Append(ITEM_TYPE appendMe);
int ShiftRight(int shiftHere);
int ShiftLeft(int shiftHere);
int InsertBefore(ITEM_TYPE insertThis, int insertHere);
int InsertAfter(ITEM_TYPE insertThis, int insertHere);
int Delete(int deleteHere);
void DeleteRepeats();
int NumUsed();
void Sort();
void Reverse();
string ErrorDescr(int failCode);
//-----------------------------------------operators:-----------------------------------------
ITEM_TYPE& operator [] (ITEM_TYPE x);
private:
//-----------------------------------------member vars:-----------------------------------------
ITEM_TYPE a[MAX];
int numUsed;
};
#endif // PARTIALARRAY_H
And here are the class functions:
#include "partialarray.h"
#include <iostream>
#include <string.h>
using namespace std;
//-----------------------------------------ctors:-----------------------------------------
PartialArray::PartialArray()
{
numUsed=0;
}
PartialArray::PartialArray(const int init[], int used)
{
numUsed = used;
for(int i=0; i<numUsed; i++)
{
a[i]=init[i];
}
}
//-----------------------------------------member functions:-----------------------------------------
//Prints the array up to its last used element
void PartialArray::PrintArray()
{
for(int i=0; i<numUsed; i++)
{
cout << a[i] << " ";
}
cout << endl;
}
//Searches the array for a particular value and returns the index at which the value first appears
int PartialArray::Search(ITEM_TYPE key)
{
for(int i=0; i<numUsed; i++)
{
if(a[i]==key)
return i;
}
return -1;
}
//Takes a number and appends it to the end of the array after the last interesting element
int PartialArray::Append(ITEM_TYPE appendMe)
{
if(numUsed<MAX)
a[numUsed++] = appendMe;
else
return 1;
return 0;
}
//Shifts all elements of the array to the right starting at a particular index
int PartialArray::ShiftRight(int shiftHere)
{
if(shiftHere<numUsed)
{
ITEM_TYPE save = a[numUsed-1];
for(int i=numUsed; i>=shiftHere; i--)
{
a[i] = a[i-1];
}
a[shiftHere] = save;
return 0;
}
else
return 2;
}
//Shifts all elements of the array to the left starting at a particular index
int PartialArray::ShiftLeft(int shiftHere)
{
if(shiftHere<numUsed)
{
ITEM_TYPE save = a[shiftHere];
for(int i=shiftHere; i<numUsed; i++)
{
a[i] = a[i+1];
}
a[numUsed-1] = save;
return 0;
}
else
return 2;
}
//Takes a number and a position and inserts the number before that position in the array shifting the elements to the right
int PartialArray::InsertBefore(ITEM_TYPE insertThis, int insertHere)
{
if(insertHere>numUsed)
return 2;
else
{
numUsed++;
ShiftRight(insertHere);
a[insertHere] = insertThis;
}
return 0;
}
//Takes a number and a position and inserts the number after that position in the array shifting the elements to the right
int PartialArray::InsertAfter(ITEM_TYPE insertThis, int insertHere)
{
if(insertHere>numUsed)
return 2;
else if(numUsed>=MAX)
return 1;
else
{
numUsed++;
ShiftRight(insertHere+1);
a[insertHere+1] = insertThis;
}
return 0;
}
//Takes a position and removes that item from the array, shifting all the elements to the left
int PartialArray::Delete(int deleteHere)
{
if(deleteHere <= numUsed)
{
ShiftLeft(deleteHere);
numUsed--;
return 0;
}
else
return 2;
}
//Deletes repeated elements in the array and replaces the with 0
void PartialArray::DeleteRepeats()
{
for(int i=0;i<numUsed;i++)
{
ITEM_TYPE n=a[i];
for(int j=i+1; j<numUsed;j++)
{
if(n == a[j])
{
Delete(j);
j--;
}
}
}
}
//Returns number of interesting elements in the array
int PartialArray::NumUsed()
{
return numUsed;
}
//Utilizes a bubble sort algorithm
void PartialArray::Sort()
{
bool swap = true;
int j = 0;
int save;
while (swap==true)
{
swap = false;
j++;
for (int i = 0; i < numUsed - j; i++)
{
if (a[i] > a[i + 1])
{
save = a[i];
a[i] = a[i + 1];
a[i + 1] = save;
swap = true;
}
}
}
}
void PartialArray::Reverse()
{
for(int i=0;i<numUsed-1;i++)
{
ITEM_TYPE save = a[numUsed-1];
ShiftRight(i);
a[i] = save;
}
}
//Returns the appropriate error description for a particular fail code
string PartialArray::ErrorDescr(int failCode)
{
switch(failCode)
{
case -1:
return "ERROR: item not found";
break;
case 1:
return "ERROR: array is full";
break;
case 2:
return "ERROR: unused index";
break;
default:
return "UNKNOWN ERROR";
break;
}
}
//-----------------------------------------operators:-----------------------------------------
ITEM_TYPE& PartialArray::operator [](ITEM_TYPE x)
{
return a[x];
}
Now, here is where things have gotten tricky. To build the two dimensional array class, I'm supposed to create an array of arrays. I'm at a loss as to how I should go about this, and after tinkering and googling for a few hours I've only become more confused. Specifically, the <<, [], and [](constant version) operators and the TwoDArray constructor have thrown me for a loop, and I'm stuck without much sense of what to do next. Here is the TwoD header file:
#ifndef TWODARRAY_H
#define TWODARRAY_H
#include "partialarray.h"
#include <iostream>
#include <string.h>
typedef int ITEM_TYPE;
class TwoDArray
{
friend ostream& operator << (ostream &outs, const TwoDArray& printMe);
public:
//ctors:
TwoDArray();
//member functions:
//PartialArray& operator [](int index); //[ ] operator for the TwoDArray object
//PartialArray operator [](int index) const; //[ ] operator for the TwoDArray object (const version)
int Append(int appendMe, int row);
int InsertBefore(int insertMe, int row, int column);
int InsertAfter(int insertMe, int row, int column);
int Delete(int row, int column);
bool Search(ITEM_TYPE key, int &row, int &column);
private:
//member vars:
PartialArray a[MAX];
};
#endif // TWODARRAY_H
And this is what I've tried to define thus far:
TwoDArray::TwoDArray()
{
const int array0[]= {0};
PartialArray array(array0, MAX);
}
ostream& operator << (ostream &outs, const TwoDArray& printMe)
{
for(int i=0;i<MAX;i++)
{
outs << printMe.a[i];
}
return outs;
}
Ideally, the << operator will print an m by n array of items.
This is my program to solve a sudoku puzzle by using a backtracking algorithm. The program will recursively call itself until it is either solved or if it is unsolvable. The problem is that when I run it the compiler says that the sudoku_backtracker() function call in line 19 of sudoku_solver.cpp is ambiguous. Can someone please explain to me why it says that and how can I fix it. If there are other problems I would also appreciate the help. Thanks alot.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "sudoku_solver.hpp"
int main()
{
std::vector< std::vector<int> > board(9,std::vector<int>(9));
int i =0,j=0;
for(std::string line;std::getline(std::cin,line);)
{
if(i==9)
{
i=0;
break;
}
std::stringstream line_stream(line);
for(std::string token;std::getline(line_stream,token,' ');)
{
if(j==9)
{
j=0;
}
board[i][j] = std::stoi(token);
j++;
}
i++;
}
if(sudoku_backtracker(board)==1)
{
for(int i = 0;i<9;i++)
{
for(int j = 0;j<9;j++)
{
std::cout<<board[i][j];
}
std::cout<<endl;
}
}
return 0;
}
/* This is sudoku_solver.hpp placed here for better organization on stackoverflow*/
#ifndef __SUDOKU_SOLVER_HPP__
#define __SUDOKU_SOLVER_HPP__
#include <vector>
int sudoku_backtracker(std::vector< std::vector<int> > board);
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board);
bool checks_num_is_valid(std::vector< std::vector<int> > board,int row,int column,int number);
#endif //__SUDOKU_SOLVER_HPP__
/*this is sudoku_solver.cpp but I placed it after the header file so I can put it in block on stackoverflow*/
#include "sudoku_solver.hpp"
#include <iostream>
#include <string>
int sudoku_backtracker(std::vector< std::vector<int> > &board)
{
int test_num = 1;
std::pair<int,int> empty_spot = find_empty_spot(board);
if(empty_spot.first == -1)
{
return 1;
}
while(test_num != 10)
{
if(checks_num_is_valid(board,empty_spot.first,empty_spot.second,test_num))
{
board[empty_spot.first][empty_spot.second] = test_num;
int recursive_sudoku = sudoku_backtracker(board);
if(recursive_sudoku==1)
{
return 1;
}
board[empty_spot.first][empty_spot.second] = 0;
}
test_num++;
}
return 0;
}
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board,int row,int column)
{
for(int row=0;row<9;row++)
{
for(int column=0;column<9;column++)
{
if(board[row][column] == 0){return std::make_pair(row,column);}
}
}
return std::make_pair(-1,-1);
}
bool checks_num_is_valid(std::vector< std::vector<int> > board, int row,int column, int number)
{
bool num_not_in_column = true;
bool num_not_in_row = true;
bool num_not_in_box = true;
//box_start_row as bsr and box_start_column as bsc
//this is the starting point to check the numbers inside the box and make
//sure the test number is valid
int bsr = 0,bsc = 0;
//checks the numbers in the same column but different rows
for(int i =0;i<9;i++)
{
if(i==row){continue;}
if(board[i][column] == number){num_not_in_column = false;break;}
}
//checks numbers in the same row but different columns
for(int i = 0;i<9;i++)
{
if(i==column){continue;}
if(board[row][i] == number){num_not_in_row = false;break;}
}
//checks wether the numer is int the same box
if(row<=2){bsr =0;}
if(row>=3 && row<=5){bsr = 3;}
if(row>=6 && row<=8){bsr = 6;}
if(column <=2){bsc =0;}
if(column>=3 && column<=5){bsc=3;}
if(column>=6 && column<=8){bsc=6;}
//double for loop to check all the values inside the box
for(bsr;bsr<bsr+3;bsr++)
{
for(bsc;bsc<bsc+3;bsc++)
{
if(bsr==row && bsc==column)
{continue;}
else
{
if(board[bsr][bsc] == number)
{
num_not_in_box = false;
}
}
}
}
bool result = num_not_in_row && num_not_in_column && num_not_in_box;
return result;
}
The declaration :
int sudoku_backtracker(std::vector< std::vector<int> > board);
Does not match the definition :
int sudoku_backtracker(std::vector< std::vector<int> > &board) { ... }
^^^
I am trying to run this program but it just runs for a very long time when it is supposed to only take a couple seconds. I would appreciate it if I could get help on what is wrong with my code and what i need to fix.
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include "sudoku_solver.hpp"
int main()
{
std::vector< std::vector<int> > board(9,std::vector<int>(9));
int i =0,j=0;
for(std::string line;std::getline(std::cin,line);)
{
if(i==9)
{
i=0;
break;
}
std::stringstream line_stream(line);
for(std::string token;std::getline(line_stream,token,' ');)
{
if(j==9)
{
j=0;
}
board[i][j] = std::stoi(token);
j++;
}
i++;
}
if(sudoku_backtracker(board)==1)
{
for(int i = 0;i<9;i++)
{
for(int j = 0;j<9;j++)
{
std::cout<<board[i][j];
}
std::cout<<endl;
}
}
return 0;
}
sudoku_solver.hpp:
#ifndef __SUDOKU_SOLVER_HPP__
#define __SUDOKU_SOLVER_HPP__
#include <vector>
int sudoku_backtracker(std::vector< std::vector<int> > &board);
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board);
bool checks_num_is_valid(std::vector< std::vector<int> > board,int row,int column,int number);
#endif //__SUDOKU_SOLVER_HPP__
sudoku_solver.cpp:
#include "sudoku_solver.hpp"
#include <iostream>
#include <string>
int sudoku_backtracker(std::vector< std::vector<int> > &board)
{
int test_num = 1;
std::pair<int,int> empty_spot = find_empty_spot(board);
if(empty_spot.first == -1)
{
return 1;
}
while(test_num != 10)
{
if(checks_num_is_valid(board,empty_spot.first,empty_spot.second,test_num))
{
board[empty_spot.first][empty_spot.second] = test_num;
int recursive_sudoku = sudoku_backtracker(board);
if(recursive_sudoku==1)
{
return 1;
}
board[empty_spot.first][empty_spot.second] = 0;
}
test_num++;
}
return 0;
}
std::pair<int, int> find_empty_spot(std::vector< std::vector<int> > board)
{
for(int row=0;row<9;row++)
{
for(int column=0;column<9;column++)
{
if(board[row][column] == 0){return std::make_pair(row,column);}
}
}
return std::make_pair(-1,-1);
}
bool checks_num_is_valid(std::vector< std::vector<int> > board, int row,int column, int number)
{
bool num_not_in_column = true;
bool num_not_in_row = true;
bool num_not_in_box = true;
//box_start_row as bsr and box_start_column as bsc
//this is the starting point to check the numbers inside the box and make
//sure the test number is valid
int bsr = 0,bsc = 0;
//checks the numbers in the same column but different rows
for(int i =0;i<9;i++)
{
if(i==row){continue;}
if(board[i][column] == number){num_not_in_column = false;break;}
}
//checks numbers in the same row but different columns
for(int i = 0;i<9;i++)
{
if(i==column){continue;}
if(board[row][i] == number){num_not_in_row = false;break;}
}
//checks wether the numer is int the same box
if(row<=2){bsr =0;}
if(row>=3 && row<=5){bsr = 3;}
if(row>=6 && row<=8){bsr = 6;}
if(column <=2){bsc =0;}
if(column>=3 && column<=5){bsc=3;}
if(column>=6 && column<=8){bsc=6;}
//double for loop to check all the values inside the box
for(bsr;bsr<bsr+3;bsr++)
{
for(bsc;bsc<bsc+3;bsc++)
{
if(bsr==row && bsc==column)
{continue;}
else
{
if(board[bsr][bsc] == number)
{
num_not_in_box = false;
}
}
}
}
bool result = num_not_in_row && num_not_in_column && num_not_in_box;
return result;
}
You have two nested infinite loops. bsr<bsr+3 is always true, regardless of bsr value. Except when it overflows, but that's undefined behaviour and the compiler is allowed to optimize that to true.
for(bsr;bsr<bsr+3;bsr++)
{
for(bsc;bsc<bsc+3;bsc++)