Search Vertically and Horizontally in 2D Array - c++

Basically I want to do a search Horizontally, and also Vertically. Right now I am doing this:
void checkHorizontal()
for (int iii = 1; iii<Row;; iii++)
{
for (int jjj = 1; jjj<Col; jjj++) //for every col
{
if(Array[iii][jjj]==sign)
{
//do something
}
else
{
//do something else
}
}
}
void checkVertical()
for (int iii = 1; iii<Col;; iii++)
{
for (int jjj = 1; jjj<Row; jjj++) //for every row
{
if(Array[jjj][iii]==sign)
{
//do something
}
else
{
//do something else
}
}
}
Yet, except the check function inside the for loop and the if statement, everything else is the same. And I want to reduce duplicate code, so what can I do to make a more generic function and caller just need to pass in saying if they want to do a Horizontal search or Vertical search (i.e. void check(string mode) and caller just check("Vertical"))
I know I can get pass the check function inside the for loop by doing something like this:
if (mode == "Horizontal")
{
firstBoundary = cGameBoard.m_nRow;
secondBoundary = cGameBoard.m_nCol;
}
else if (mode == "Vertical")
{
firstBoundary = cGameBoard.m_nCol;
secondBoundary = cGameBoard.m_nRow;
}
void check(string mode)
for (int iii = 1; iii<firstBoundary;; iii++)
{
for (int jjj = 1; jjj<secondBoundary; jjj++)
{
if(Array[jjj][iii]==sign)
{
//do something
}
else
{
//do something else
}
}
}
the problem is the if statement, don't know the best way of swapping the array except doing a function call to do it.
My proposal:
bool if(string mode, int& iii, int &jjj, array,string sign)
{
if(mode=="Horizontal")
return array[iii][jjj]==sign;
else if(mode=="Vertical")
return array[jjj][iii]==sign;
}
And call this function inside if statement

Your solution should work.
void check(bool dir){ // Using a bool will have better performance for checking the mode than string comparisons. Especially since you only have two directions
size_t iEnd = (dir)? cols : rows;
size_t jEnd = (dir)? rows : cols;
for (size_t i = 0; i < iEnd; ++i){
for (size_t j = 0; j < jEnd; ++j){
if(cond(i, j, dir)){
// Do something
} else {
// Do something else
}
}
}
}
bool cond(const size_t& i, const size_t& j, bool dir){
if (dir){
return array[i][j] == sign;
} else {
return array[j][i] == sign;
}
}
You could achieve the same results by using recursion
void check(size_t i, size_t j, bool dir){
if (ROW + COL - (i+j) == 1) return; /* end recursion */
if (i == ROW) return check(0, j+1, dir);
if (j == COL) return check(i+1, 0, dir);
if (array[i][j] == sign){
// Do Something
} else {
// Do Something Else
}
if (dir)
return check(i+1, j, dir);
return check(i, j+1, dir);
}
You're compiler should be able to figure out this only uses tail recursion and you don't have to worry about stack frame limit.

Related

why am I getting segmentation fault? I am trying to solve the rat in a maze problem

why am I getting segmentation fault? I am trying to solve the rat in a maze problem.
Below is the code that is giving me the segmentation fault
May be there is some fault is passing 2D array to functions but seems alright to me
I have applied the base conditions in function rinm and passing the solution matrix as well as the user input matrix from the main().
bool rinm(int** maze,int** sol,int n, int x, int y)
{
if(x==n-1 && y==n-1)
{
sol[x][y]=1;
//print the path
for (int i = 0; i < n; ++i)
{
/* code */
for (int j = 0; j < n; ++j)
{
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
return true;
}
else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0)
{
return false;
}
sol[x][y]=1;
bool up=rinm(maze,sol,n,x-1,y);
bool down=rinm(maze,sol,n,x+1,y);
bool right=rinm(maze,sol,n,x,y+1);
bool left = rinm(maze,sol,n,x,y-1);
sol[x][y]=0;
if(up||down||right||left)
{
return true;
}
}
This is my main function.
int main()
{
int n;
cin>>n;
int** maze=new int*[n];//rows
for (int i = 0; i < n; ++i)
{
maze[i]=new int [n]; // columns
}
for (int i = 0; i < n; ++i)
{
for(int j=0; j<n;j++)
{
cin>>maze[i][j];
}
}
int** sol=new int*[n];
for (int i = 0; i < n; ++i)
{
sol[i]=new int [n]; // columns
}
for (int i = 0; i < n; ++i)
{
for(int j=0; j<n;j++)
{
sol[i][j]=0;
}
}
bool path=rinm(maze,sol,n,0,0);
if(path==false)
cout<<"path doesnot exist\n";
return 0;
}
where am I going wrong?
The problem is that keep revisiting the same cells because you have not checked whether you are visiting a cell for the first time or not.
For example for the input:
2
1 1
0 1
I will enter the sequence of moves of (x, y) and you can see that it will be stuck in an infinite loop.
(0, 0)
-> (-1, 0) (up function call, returns false since x < 0)
-> (1, 0) (down function call, return false since maze[1][0] = 0)
-> (0, 1)
-> (-1, 1) (up function call, returns false since x < 0)
-> (1, 1) (down function call, solution found. Print sol matrix)
-> (0, 2) (right function call, returns false since y >= 2)
-> (0, 0) (left function call)
The problem lies here. Now you are back to (0, 0) and the recursion keeps on running without any termination. This results in huge memory allocation of recursion stack and you get Segmentation Fault.
I hope you are able to understand the problem here. If you are still in doubt, just print (x, y) as soon as you enter the loop and you will see this happening.
Here are the changes I made in the code.Here's the corrected code. This will print all available paths to reach the destination.
The function returns false if sol[x][y] == 1 which means that you have visited the cell (x, y) earlier as well.
bool rinm(int** maze,int** sol,int n, int x, int y)
{
if(x==n-1 && y==n-1)
{
sol[x][y]=1;
//print the path
for (int i = 0; i < n; ++i)
{
/* code */
for (int j = 0; j < n; ++j)
{
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
return true;
}
else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0 || sol[x][y]==1)
{
return false;
}
sol[x][y]=1;
bool up=rinm(maze,sol,n,x-1,y);
bool down=rinm(maze,sol,n,x+1,y);
bool right=rinm(maze,sol,n,x,y+1);
bool left = rinm(maze,sol,n,x,y-1);
sol[x][y]=0;
if(up||down||right||left)
{
return true;
}
return false;
}
To print any one path to the destination, you can keep a global variable and initialize that variable whenever any path is found and then return false again if that variable is initialized. The code for just one path path is below.
int c = 0;
bool rinm(int** maze,int** sol,int n, int x, int y)
{
if(x==n-1 && y==n-1)
{
c = 1;
sol[x][y]=1;
//print the path
for (int i = 0; i < n; ++i)
{
/* code */
for (int j = 0; j < n; ++j)
{
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
return true;
}
else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0 || sol[x][y]==1 || c == 1)
{
return false;
}
sol[x][y]=1;
bool up=rinm(maze,sol,n,x-1,y);
bool down=rinm(maze,sol,n,x+1,y);
bool right=rinm(maze,sol,n,x,y+1);
bool left = rinm(maze,sol,n,x,y-1);
sol[x][y]=0;
if(up||down||right||left)
{
return true;
}
return false;
}
Here are the changes represented for easy understanding.
Avoid using native 2d arrays. Replace them with a simple 1d valarray or vector and access it's elements using you own simple method that transforms x and y coords into a simple index. You'll save yourself from many headaches...
class Maze
{
private:
std::valarray<int> _data;
int _width, _height;
public:
Maze(int width, int height) : _data(width * height)
{
_width = width;
_height = height;
}
int& item(int x, int y)
{
return _data[y * _width + x];
}
// ...
}

Longest Palindrome in integer array

I want to find the largest palindrome in an integer array. I tried making my own algorithm and not looking at the online ones. But this is not working. I tried doing debugging but couldn't get it to work.
Sample input:
"1367611342142412431113424823782"
Output: 113421424124311
void palindrome()
{
int max = 0;
int len;
int start;
int end;
int st=0,en=0;
bool palin = false;
for(int i=0;i<size;i++)
{
for(int j=size-1; j>=0;j--)
{
if(array[i] == array[j])
{
start = i;
end = j;
while(j==i+1 || j+1 == i || j == i )
{
if(array[i] == array[j])
{
i++;
j--;
palin = true;
}
else
{
palin = false;
break;
}
}
i= start;
j= end;
}
if(palin == true)
{
len = end - start;
if(len>max)
{
cout<<" "<<st<<" "<<en<<endl;
st=i;
en =j;
max = len;
}
}
}
}
cout<<endl;
cout<<st<<" "<<en<<endl;
ofstream file("output.txt");
for(int i=st;i<=en;i++)
{
file<<array[i];
}
}
There is solution
#include <iostream>
#include <string>
struct Result
{
int fromIndex, toIndex;
Result(int fromIndex, int toIndex){
this->fromIndex = fromIndex;
this->toIndex = toIndex;
}
int length(){
return toIndex - fromIndex;
}
};
bool isPalindrome(std::string &s, int left, int right){
while(left <= right){
if(s[left] != s[right]){
return false;
}
left ++;
right --;
}
return true;
}
std::string solve(std::string &s){
int startIndex = 0;
int toIndex = s.size() - 1;
Result result(0,0);
while(true){
if(isPalindrome(s, startIndex, toIndex)){
if(result.length() < (toIndex - startIndex)){
result.fromIndex = startIndex;
result.toIndex = toIndex;
}
}
toIndex --;
if(toIndex <= startIndex){
toIndex = s.size() - 1;
startIndex++;
}
if(startIndex == s.size() - 1){
break;
}
}
std::string str = "";
for (int i = result.fromIndex; i <= result.toIndex; ++i)
{
str += s[i];
}
return str;
}
int main()
{
std::string s = "1367611342142412431113424823782";
std::string result = solve(s);
std::cout << "Longest palindrome is: "<< result;
return 0;
}
You need to think in more structural way. Split your task in to sub-tasks first. In this case there are to sub-tasks:
1. go over all possible combinations
2. check if this combination is a palindrome.
Each task is another function - this way it is easier to think, read code and debug.
(In case you want to write it to file - it is a third task!)
Here is the code for the "go over all possible combinations". I guess you will find yourself how to check a single array if it is a palindrome.
#include <iostream>
using namespace std;
bool isPalindrome(int* arr, int size);
bool findLargestPalindrome(int* arr, int size);
int main()
{
int arr[] = { 1,3,6,7,6,1,1,3,4,2,1,4,2,4,1,2,4,3,1,1,1,3,4,2,4,8,2,3,7,8,2 };
int arrSize = 31;
findLargestPalindrome(arr, arrSize);
}
bool findLargestPalindrome(int* arr, int size)
{
for (int testSize = size; testSize > 0; testSize--)
{
int startIndex = 0;
while (testSize + startIndex <= size)
{
int* arrayToTest = &(arr[startIndex]);
if (isPalindrome(arr, testSize))
{
//TODO: you found it - do with it whatever you want
return true;
}
startIndex++;
}
}
return false;
}
bool isPalindrome(int* arr, int size)
{
//TODO: your code for single palindrome
return false;
}

solve sudoku with backtracking - C++

So I am trying to solve sudoku with backtracking
And with this example :
example_pic
I hard-coded some of the indexes in the two dimensional array with numbers on places given from webSudoku (picture above).
It definitely has solutions but, my code prints "solution doesn't exist
Here is my code :
#include <stdio.h>
int a[10][10]= {{2,0,0,0,9,0,0,3,1},
{0,0,3,5,0,6,0,2,0},
{0,0,8,1,3,0,5,4,0},
{7,2,0,0,0,9,0,0,4},
{4,0,0,0,0,0,0,0,8},
{3,0,0,6,0,0,0,9,5},
{0,7,6,0,4,5,1,0,0},
{0,1,0,9,0,7,4,0,0},
{5,3,0,0,8,0,0,0,6}};
bool is_valid(int x, int y, int value){
if(a[x][y] != 0) return false;
//check_row and column
for(int tmp=1; tmp<=9; tmp++){
if(value == a[x][tmp]) return false;
}
for(int tmp=1; tmp<=9; tmp++){
if(value == a[tmp][y]) return false;
}
//check in 3*3 block
int x_s = (x-1)/3*3 + 1;
int y_s = 3*((y+2)/3-1)+1;
for(int ch_x = x_s; ch_x<x_s+3; ch_x++){
for(int ch_y=y_s; ch_y<y_s+3; ch_y++){
if(ch_x!=x && ch_y!=y){
if(value==a[ch_x][ch_y]) return false;
}
}
}
return true;
}
bool find(int &x, int &y){
// check if valid cells are exists
for(x=1; x<=9; x++){
for(y=1; y<=9; y++){
if(a[x][y] == 0)
return true;
}
}
return false;
}
bool solve(){
int x,y;
//base::case
if(!find(x,y)) return true;
for(int cand = 1; cand <=9; cand++){
if(is_valid(x,y,cand)){
a[x][y] = cand;
if(solve()) return true;
a[x][y] = 0;
}
}
return false;
}
void print(){
//print the sudoku plate
for(int i=1;i<=9; i++){
for(int j=1; j<=9; j++){
printf("%2d",a[i][j]);
}
printf("\n");
}
return ;
}
int main(){
//Fill in some empty grid with the known values
/*for(int i=1; i<=9; i++){
for(int j=1; j<=9; j++){
scanf("%1d",&a[i][j]);
}
}*/
if (solve()) print();
else printf("No solution exists\n");
return 0;
}
I guess my 'solve function' or 'is_valid' function is not working right.
In 'is_valid' function, if there is problem it would be
bool find(int &x, int &y){
// check if valid cells are exists
for(x=1; x<=9; x++){
for(y=1; y<=9; y++){
if(a[x][y] == 0)
return true;
}
}
return false;
}
But, I also hard-coded this part and in my scope it doesn't seem like have problem.
In 'solve function'
bool solve(){
int x,y;
//base::case
if(!find(x,y)) return true;
for(int cand = 1; cand <=9; cand++){
if(is_valid(x,y,cand)){
a[x][y] = cand;
if(solve()) return true;
a[x][y] = 0;
}
}
return false;
}
I cant figure out where i got it wrong. If you find any other mistakes in the solve() function - let me know. Because I am not sure I understand the "backtracking" thing completely...
p.s. : reference I read (https://see.stanford.edu/materials/icspacs106b/H19-RecBacktrackExamples.pdf)
There are a few mistakes
You are mixing up (x, y) and (row, col) addressing (row is y, not x). Choose a representation and stick to it
There is a typo in is_valid because the check on (c, x) should be on (c, y) (or (y, c) depending on convention but surely using y and not x again)
The 3x3 sub-block computation is wrong... a correct formula could be for example int start_x = (x-1)/3*3 + 1, start_y = (y-1)/3*3 + 1;
Fixing all that the code works on the given example

How to check if all the values of an array are equal to 0?

The context of the program is a game involving pegs and discs. The user inputs the amount of pegs (max of 20) and the amount of discs on each peg (max of 10). Two players go back and forth removing any amount of discs on a single peg each turn, given that there are enough discs to remove on that peg. The player to remove the last disc loses.
The number of discs are stored in an array, where the index of the array corresponds the peg number. I have a boolean function that checks whether or not the pegs are empty of discs, implying someone has won. There is some logical error in my code but I can't figure out what it is:
bool checkPegs(int array[], int size)
{
int checker(0);
for (int i = 0; i < size; i++)
{
if(array[i] = 0)
{
return true;
}
else
{
return false;
}
}
}
bool checkPegs(int array[], int size)
{
for (int i = 0; i < size; i++)
{
if(array[i] != 0)
{
return false;
}
}
return true;
}
try memcmp instead of having separate function with for loop:
int zeros[sizeof(yourArray)];
if(memcmp(yourArray,zeros,sizeof(yourArray))==0)
//do things
else
//do things
if(array[i] = 0)
That doesn't compare array[i] with 0, it assigns 0 to array[i]. You want array[i] == 0.
if(array[i] == 0)
{
return true;
}
else
{
return false;
}
The second issue is that you only check the first element, then return based on that. You should check every element to ensure they are non-zero:
for (int i = 0; i < size; i++)
{
if(array[i] != 0) {
return false;
}
}
Finally, you don't handle the case that size is 0. In that case, you should return true.
bool checkPegs(int array[], int size)
{
for (int i = 0; i < size; i++)
{
if(array[i] != 0) {
return false;
}
}
return true;
}
there are two errors here
bool checkPegs(int array[], int size)
{
int checker(0);
for (int i = 0; i < size; i++)
{
if(array[i] = 0) // the first one use '==' instead of '='
{
return true; // the second one, you are testing the first element only
}
else
{
return false;
}
}
}
here how it should be
bool checkPegs(int array[], int size)
{
for (int i = 0; i < size; i++)
{
if(array[i] )
return false; // return false at the first found
}
return true; //all elements checked
}
The way you wrote your code cannot work, for you are actually considering only the first element because of the two return statements in the if/else. Moreover, you use an assignment statement instead of a comparison.
It follows a reviewed example:
bool checkPegs(int *array, int size) {
for (int i = 0; i < size; i++) {
if(array[i] != 0) { return false; }
}
return true;
}
Keep in mind that it can be optimized and you can do the same using standard utilities, but I assume that you are learning to code and so it's worth to write it for yourself.

N queen using c++ and backtracking using a dynamic 2D array

I've been trying to solve the N queen problem using backtracking. Most of the approaches that I found online, involved vectors, making it difficult for me to visualize the solutions as some applets on the Internet do.
The solution I came up with, is giving me many problems(which i have a feeling are related to indexing of the dynamic 2D array used) and I'm not able to figure it out using Dev-C++ debugger.Any help and/or constructive criticism is highly appreciated. Many thanks in advance.
Here is the solution that i came up with:
#include<iostream>
#include<string.h>
#include<conio.h>
using namespace std;
void display(char** b, int len);
void initialize(char** &b, int k);
void consider1strow(char ** b, int len);
void markunsafe(char** board, int rowno, int colno);
void marksafe(char** board, int rowno, int colno);
void considerrow(char** board, int rowno);
void backtrack(char** board, int rowno);
bool checksafety(char** board, int rowno, int colno);
void place(char** board, int rowno, int colno);
void solve(char** board, int len);
int state[20] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
int len;
void display(char** board, int len)
{
int i, j;
cout << endl << "The current state of the board:" << endl;
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
cout << board[i][j];
}
cout << endl;
}
}
void initialize(char** &b, int k)
{
int i, j;
//create dynamic board
b = new char*[k];
for (i = 0; i < k; i++)
{
b[i] = new char[k];
}
//initialize array
for (i = 0; i < k; i++)
{
for (j = 0; j < k; j++)
{
b[i][j] = '-';
}
}
}
void consider1strow(char ** board, int len)
{
int col;
cout << "Enter the column to try for the first row!";
cin >> col;
board[0][col - 1] = 'Q';
state[0] = col - 1;
markunsafe(board, 0, col - 1);
display(board, len);
}
void markunsafe(char** board, int rowno, int colno)
{
int i, j;
//mark row as unsafe
for (i = 0; i < len; i++)
{
board[rowno][i] = 'x';
}
//mark column as unsafe
for (i = 0; i < len; i++)
{
board[i][colno] = 'x';
}
//mark unsafe diagonals
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
if ((rowno + colno) == (i + j))
{
board[i][j] = 'x'; //check if index gives a problem of +/- 1
}
if ((rowno - colno) == (i - j))
{
board[i][j] = 'x'; //check if index gives a problem of +/- 1
}
}
}
board[rowno][colno] = 'Q';
}
void marksafe(char** board, int rowno, int colno)
{
int i, j;
//mark row as safe
for (i = 0; i < len; i++)
{
board[rowno][i] = '-';
}
//mark column as unsafe
for (i = 0; i < len; i++)
{
board[i][colno] = '-';
}
//mark unsafe diagonals
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
if ((rowno + colno) == (i + j))
{
board[i][j] = '-'; //check if index gives a problem of +/- 1
}
if ((rowno - colno) == (i - j))
{
board[i][j] = '-'; //check if index gives a problem of +/- 1
}
}
}
}
void considerrow(char** board, int rowno)
{
bool safe = 0;
int i;
for (i = 0; i < len; i++)
{
safe = checksafety(board, rowno, i);
if (safe && (i >= state[rowno]))
{
break;
}
}
if (safe && (i >= state[rowno]))
{
place(board, rowno, i);
}
else if (!safe)
{
backtrack(board, rowno);
}
}
void backtrack(char** board, int rowno)
{
marksafe(board, rowno - 2, state[rowno - 2]);
considerrow(board, rowno);
}
bool checksafety(char** board, int rowno, int colno)
{
if (rowno == 0)
{
return 1;
}
else if (board[rowno][colno] == 'x')
{
return 0;
}
else if (board[rowno][colno] == '-')
{
return 1;
}
}
void place(char** board, int rowno, int colno)
{
board[rowno][colno] = 'Q';
state[rowno] = colno;
markunsafe(board, rowno, colno);
}
void solve(char** board, int len)
{
int i = 0;
if (i == len)
{
display(board, len);
}
else
{
consider1strow(board, len);
for (i = 1; i < len; i++)
{
considerrow(board, i);
}
}
}
int main()
{
char** board;
cout << "Enter the size of the board!";
cin >> len;
initialize(board, len);
solve(board, len);
getch();
}
It is running after the initial configuration, but you're not printing it. Change this (inside solve):
for(i=1;i<len;i++)
{considerrow(board,i);}
for this:
for(i=1; i<len; i++) {
considerrow(board,i);
display(board,len);
}
Besides that, there is a problem with the way you are doing backtracking. If no options are available, you are removing the queen from the previous row (that's ok) and then you are marking every cell it was attacking as safe (not ok). The problem is that some of these cells may be under attack by a different queen, so you cannot mark them as safe. Furthermore, you do not place a different queen on that row. I propose some solutions:
First, make it recursive: considerrow would call itself with the following row, and return true (1) if it succeeds or false (0) if it fails. If it fails with the next row, you can use the next queen in the current row and call considerrow again, until you succeed or run out of columns, in which case you return false.
To consider a different queen on a certain row, you can do two things: create a copy of the board which you would pass to considerrow for the next row (and thus keeping a 'before' copy to try a different queen), or mark every cell as safe, and then check all the existing queens to mark cells unsafe.
Edit:
To make it recursive, we are going to make considerrow call itself with the next value.
bool considerrow(char** board,int rowno) {
//Print the board
display(board,len);
bool safe=0;
int i;
for(i=0; i<len; i++) {
safe=checksafety(board,rowno,i);
if(safe) {
place(board,rowno,i);
//Is this the last row? If so, we suceeded
if (rowno==len-1) return 1;
//Call itself with next row, check if suceeded
if (considerrow(board,rowno+1))
return 1;
else //Failed, try a different row
backtrack(board,rowno);
}
}
return 0; //If we got here, then we ran out of colums. Return failure
}
The backtrack function can be modified to revert the current row like this:
void backtrack(char** board, int rowno) {
//Clear the current row
marksafe(board,rowno,state[rowno]);
//Check that every cell attacked by another queen is marked unsafe
for(int i=0; i<rowno; i++) markunsafe(board,i,state[i]);
}
Doing that, solve will only need to call the first row:
void solve(char** board,int len) {
considerrow(board,0);
display(board,len);
}