So I initialized an array as array[8][8] let's suppose that I'm at point (row, column) and for example, it is row 4 column 4 and I want to loop through every diagonal direction (southeast, southwest, northeast, northwest)
so I wrote 4 different functions to check each direction alone, and here is an example for Northeast
for(int i = 0; i < 8; i++)
for(int j = 0; j < 8; j++)
if(array[i - 1][j+1] == 'x')
{
count = count + 1;
}
is there is a way to loop in all diagonal directions at the same time?
another problem is what about getting out of bounds, like if the point is (7,7), then there will be no value in northeast because it will exceed the array bounds array[6][8], and that is out of array bounds. How can I deal with this problem? or does the compiler return an error when it happens?
You can of course check in each direction, e.g.
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
if (check_north_east(array, i, j))
++count;
if (check_north_west(array, i, j))
++count;
if (check_south_east(array, i, j))
++count;
if (check_south_west(array, i, j))
++count;
}
}
The compiler will happily go beyond the array bounds. So you must make sure, the code won't do it, and check yourself
const int NROWS = 8, NCOLS = 8;
bool check_north_east(char array[][NCOLS], int row, int col)
{
if (row <= 0 || col >= NCOLS - 1)
return false;
return array[row - 1][col + 1] == 'x';
}
Related
I implemented this Connect 4 Winning horizontal function but I cannot for the life of me figure out why my c++ horizontal function will not work it is a 2d array
for (int j = 0; j < row - 3; j++) {
for (int i = 0; i < column; i++) {
if (Board[i][j] == charvar && Board[i][j + 1] == charvar && Board[i][j + 2] == charvar && dyBoard[i][j + 3] == charvar) {
return charvar;
}
}
}
Wouldnt my array go from [0][0] to [0][1] and so on? I already tried without the -3 but that dosnt seem to work.
The first array index is row, the second is column, so loops should look like this:
for (int i = 0; i < rowcount; i++) {
for (int j = 0; j < columncount - 3; j++) {...
There are so many questions regarding Nqueens problem here. However, my implementation is different. My code checks with the board if queen placement is possible, instead of checking with the position of the previous queen.
It goes like this:
initially, the board has all zeros filled. The algorithm starts with the position (0,0). Then, it checks
row-wise per column to find the first 0. After finding the first zero, it changes the zero to one.
From this point onward, my logic differs. Instead of going to the next column, it first disables all the
positions, which the currently placed queen attacks, i.e. writes -1 on those places, i.e., row, column,
upper diagonal and lower diagonal. Now, the column value increments, and instead of check with the previous queen,
it simply has to find the first zero. Then again, relative positions get disabled.... you get the idea.
The code:
#include <iostream>
int board[8][8];
void printBoard() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
std::cout << board[i][j] << " ";
}
std::cout << "\n";
}
}
void disablePositions(int row, int col) {
//disable row
for (int j = col + 1; j < 8; j++) {
board[row][j] = 2;
}
//disable column
for (int i = 0; i < 8; i++) {
if (board[i][col] == 1) {
continue;
}
board[i][col] = 2;
}
//disable upper diagonal
for (int i = row - 1, j = col + 1; i >= 0 || j < 8; i--, j++) {
board[i][j] = 2;
}
for (int i = row + 1, j = col + 1; i < 8 || j < 8; i++, j++) {
board[i][j] = 2;
}
}
void solve(int initial_row) {
int init = initial_row;
int row = 0;
int col = 0;
while (col != 8) {
for (row = init; row < 8; row++) {
if (board[row][col] == 0) {
board[row][col] = 1;
break;
}
}
if (row == 8) {
col = 0;
initial_row++;
init = initial_row;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
board[i][j] = 0;
}
}
}
else {
init = 0;
disablePositions(row, col);
col++;
}
printBoard();
std::cout << std::endl;
}
}
int main() {
solve(0);
std::cout << std::endl;
}
This code is for 8-queens. The problem is, after it reaches the stage where it starts from [5][0], it just crashes. What is causing the issue?
Also, as it tries to make an optimal choice at every stage, would we call it greedy algorithm?
In your disable upper diagonal loops, you have the condition wrong. Using an || operation, the looping continues when either condition is true, which will lead to out-of-bounds access to the array.
Change the conditions in both for loops to be && (and).
I'm having problems taking care of forbidden memory access. I have a task to find the highest mountain of a matrix (defined as a number that is higher than the sum of square of numbers surrounding it). Code works when I hard-code it not to access elements out of a matrix, which is not a good thing at all.
How do I make sure I never try to access memory that I'm not supposed to?
typedef std::vector<std::vector<double>> Matrix;
typedef std::vector<double> Vector;
unsigned CalculateSum(Matrix mat, int counter, int x, int y)
{
unsigned sum(0);
if (x < counter) return 0;
for (int i(x - counter); i <= (x + counter); i++) {
if(y < counter) return 0;
for (int j(y - counter); j <= (y + counter); j++) {
if (i == x && j == y) continue;
sum += mat.at(i).at(j);
}
}
return sum;
}
Matrix HighestMountain(Matrix mat)
{
for (int i(0); i < mat.size(); i++) {
if (mat.at(i).size() != mat.size()) throw std::domain_error("Wrong
format");
}
Matrix insert;
Vector v;
int sum1(0), sum2(0);
int counter(1);
for (int i(0); i < mat.size(); i++) {
for (int j(0); j < mat.at(i).size(); j++) {
if(i == 0 || j == 0 || i == mat.size()-1 || j == mat.at(i).size()-1) continue;
while (CalculateSum(mat, counter, i, j) < mat.at(i).at(j)) {
insert.clear();
for (int k(i - counter); k <= counter + 2; k++) {
for (int l(j - counter); l <= counter + 2; l++) {
v.push_back(mat.at(k).at(l));
}
insert.push_back(v);
v.clear();
}
counter++;
if(counter > i || counter > j || i+counter > mat.size()-1 ||
j+counter > mat.at(i).size()-1) break;
}
}
}
return insert;
}
Start by identifying the various situations you have td deal with. Corner elements have three neighbors. Edge elements that aren’t corners have five. Interior elements have eight. So there are three distinct cases that you need code for.
Or you can use a matrix with each dimension 2 larger than your data and put zeros in all the edge elements. Then everything you’ve interested in is an interior element, with eight neighbors.
It’s all about design.
Let you have a std::vector< T > (where by T I mean any class or typename) containing n elements and you want to populate a matrix-like object, as instance an object of class boost::numeric::ublas::matrix< T >, whose dimensionality is m1 rows and m2 columns, inserting those elements one by one by rows or by columns.
First of all, it must be n <= m1 * m2 or we're trying to fill, say, 10 slots with 11 or more elements; then: if n <= m1 (respectively, n <= m2) no problems arise for a loop is enough.
But if n > m1 (n > m2) you have to split your std::vector< T > to avoid bad index issues and to populate your matrix according to your choice.
Here is my attempt:
#include <algorithm>
#include <boost/numeric/ublas/matrix.hpp>
#include <vector>
template < class T > inline void PopulateGrid(const std::vector< T >& tVector,
boost::numeric::ublas::matrix< T >& tMatrix,
char by = 'n')
{
if (tVector.size() > tMatrix.size1() * tMatrix.size2())
throw("Matrix is too small to contain all the array elements!");
else
{
switch(by)
{
case 'r' :
for (unsigned i = 0; i < tMatrix.size1(); i++)
{
for (unsigned j = 0; j < tVector.size(); j++)
{
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
}
break;
case 'c' :
for (unsigned j = 0; j < tMatrix.size2(); j++)
{
for (unsigned i = 0; i < tVector.size(); i++)
{
if (i <= tMatrix.size1())
tMatrix(i, j) = tVector[i];
else
tMatrix(i - tMatrix.size1(), j + 1) = tVector[j];
}
}
break;
default:
for (unsigned i = 0; i < tMatrix.size1(); i++)
{
for (unsigned j = 0; j < tVector.size(); j++)
{
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
}
// Following is just to populate it randomly
std::random_shuffle(tMatrix.begin1(), tMatrix.end1());
std::random_shuffle(tMatrix.begin2(), tMatrix.end2());
}
}
}
A fast main to try it:
int main()
{
std::vector< int > ciao;
for (int i = 0; i < 12; i++)
ciao.push_back(i);
boost::numeric::ublas::matrix< int > peppa(10, 10);
PopulateGrid< int >(ciao, peppa); // crashes!
/* Check failed in file C:\DevTools\boost_1_54_0/boost/numeric/ublas/functional.hpp
* at line 1371:
* j < size_j
* terminate called after throwing an instance of 'boost::numeric::ublas::bad_index'
* what(): bad index
*/
return 0;
}
The point is: I am missing some easier operations on indexes to achieve the same result and I am messing with indexes.
I will completely re-write this answer, it's more of an answer and less of a suggestion now.
Again, the problem you have is here:
for (unsigned j = 0; j < tVector.size(); j++) {
if (j <= tMatrix.size2())
tMatrix(i, j) = tVector[j];
else
tMatrix(i + 1, j - tMatrix.size2()) = tVector[j];
}
This is the inner loop of the nested for-loop construct that you are using. In here, you run through the entire vector. Upon j exceeding size2 you are not exiting the loop, but instead adressing (i+1) as the first index for tMatrix(i1,i2). And then for i2 you subtract size2 from j.
Two problems: As soon as your j exceeds size2 you will forever rewrite into the matrix i1 index of value 1.
And then, if j becomes greater than 2*size2 you will try writing out of bound indicies. For example, if the vecor contains 20 elements and you have a 7*7 matrix, you will write to vectorIndex-7 as soon as vectorIndex becomes 8. [Note that your <=tMatrix.size2() is also wrong, should be only < ). That works all the way until vectorIndex is 14 or greater, as 14-7 = 7 or great -> out of bound.
Second problem is that your outer for-loop will still do its iteration and recall the entire process for every i-value. In the end you will be at the maximum allowed i-value and in your inner loop you will try accessing (i+1). This will also give you an out of bound expection.
I would suggest something like this as a solution:
for ( std::vector<T>::iterator it = yourVector.begin(), int rowIndex = 0, colmIndex = 0;
it != yourVector.end(); ++it, colmIndex++ ) {
if ( colmIndex >= yourMatrix.size2() ) {
rowIndex++;
colmIndex = 0;
yourMatrix (rowIndex, colmIndex ) = *it;
}
else {
yourMatrix (rowIndex, colmIndex ) = *it;
}
}
This is untested and fills the vector by column. You should be able to figure out what to do for byRow yourself!
This code should produce a solved sudoku matrix, however the while statement puts it in an infinite loop. Removing the while statement gives me a matrix with some values still 99 or 0. And i can't generate 9 random numbers uniquely one by one.
IF YOU WANT TO RUN AND CHECK THE CODE, REMOVE THE WHILE STATEMENT.
int a[9][9];
int b[9][9];
int inputvalue(int x, int y, int value) //checks horizontally, vertically and 3*3matrix for conflicts
{
int i, j;
for (i = 0; i < 9; i++)
{
if (value == a[x][i] || value == a[i][y])
return 0;
}
for (i = (x / 3) * 3; i <= ((x / 3) * 3) + 2; i++)
{
for (j = (y / 3) * 3; j <= ((y / 3) * 3) + 2; j++)
if (b[i][j] == value)
return 0;
}
return value;
}
int main()
{
int i, j, k;
unsigned int s;
cout << "sudoku\n";
time_t t;
s = (unsigned) time(&t);
srand(s);
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
a[i][j] = 99;
}
for (i = 0; i < 9; i++)
{
for (j = 1; j <= 9; j++)//j is basically the value being given to cells in the matrix while k assigns the column no.
while(a[i][k]==99||a[i][k]==0)
{
k = rand() % 9;
a[i][k] = inputvalue(i, k, j);
}
}
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
getch();
}
You are using assignment =, instead of equality == here:
while(a[i][k]=99||a[i][k]=0)
^ ^
this should be:
while(a[i][k]==99||a[i][k]==0)
a[i][k]=99 will always evaluate to true since 99 is non-zero, although your original code does not compile for me under gcc as it is, so I suspect the code you are running either has some parenthesizes or is slightly different.
Also using k in the while loop before it is initialized is undefined behavior and it is unclear that your termination logic makes sense for a k that is constantly changing for each loop iteration.
Another source of the infinite loop is inputvalue which seems to get stuck returning 0 in some instances, so you need to tweak that a bit to prevent infinite loops.
Also, srand(time(NULL)); is a more common way to initialize the pseudo-random number generator