I am currently working on a code that checks the giving index neighbors (north, west, east, south) and if the neighbors have the value 0 or 11 it should return false. The start point is 0,0 which has the value 4.
This is my test function.
bool testG(int grid[ROW][COL], int row, int col) {
if (row < 0 || col < 0 || row >= ROW || col >= COL)
return false;
return grid[row][col] == 0 || grid[row][col] == 11;
}
this is my query:
if(testG(grid,-1,0) && testG(grid,0,-1) && testG(grid,1,0) && testG(grid,0,1))
{
return false;
}
and this is my 2d array that should return false if the function is called.
int grid[ROW][COL] {{ 4, 11, 1, 1 },
{ 0, 0, 1, 0 },
{ 0, 1, 5, 0},
{ 0, 5, 0,0 } };
if the array looks like this it should return true.
int grid[ROW][COL] {{ 4, 11, 1, 1 },
{ 1, 1, 1, 0 },
{ 0, 1, 5, 0},
{ 0, 5, 0,0 } };
My problem is the first two parts of the if queryif(testG(grid,-1,0) && testG(grid,0,-1) this won't return true for the 2d array above because to the west and north of the number 4 is out of bounds.
How can I optimize my code so that one part of the index is left out if it's out of bounds but if the other queries are correct it should return false?
Thanks in advance.
It looks like you want to judge if each cells are one of:
out-of-bounds
have value 0
have value 11
To realize this, the function testG should return true for not only the "have value 0" and "have value 11" case but also "out-of-bounds" case.
bool testG(int grid[ROW][COL], int row, int col) {
if (row < 0 || col < 0 || row >= ROW || col >= COL)
return true; // return true for out-of-bounds case
return grid[row][col] == 0 || grid[row][col] == 11;
}
struct location {
int row = 0;
int col = 0;
};
int get( int grid[ROW][COL], location l ) {
return grid[l.row][l.col];
}
std::vector<location> get_adjacents( location l ) {
std::vector<location> retval;
if (l.row-1 >= 0) retval.push_back( {l.row-1, l.col} );
if (l.row+1 < ROW) retval.push_back( {l.row+1, l.col} );
if (l.col-1 >= 0) retval.push_back( {l.row, l.col-1} );
if (l.col+1 < COL) retval.push_back( {l.row, l.col+1} );
return retval;
}
bool testG_adjacents( int grid[ROW][COL], location l ) {
for (auto adjacent : get_adjacents(l) )
if (!testG(grid, adjacent.row, adjacent.col))
return false;
return true;
}
this attempts to split the adjacent in-bounds logic from the test logic.
Related
Hello I am practicing working with 2d arrays in c++ and my question is for example if I want to check if 4 has either 0 or 11 to the north , east, south, west as neighbour it should return false.
this is my if
if((grid[0-1][0] == 0 || grid[0-1][0] == 11 ) &&
(grid[0+1][0] == 0 || grid[0+1][0] == 11 ) &&
(grid[0][0+1] == 0 || grid[0][0+1] ==11) &&
(grid[0][0-1] == 0 || grid[0][0-1] ==11 ))
{
return false;
}
Now my problem is since west of 4 and north of four is out of bounds it will never return false.
How could I optimise my if condition to make it return false?
This is my 2d array
int grid[ROW][COL] = {{ 4, 11, 1, 1 },
{ 0, 0, 1, 0 },
{ 0, 1, 5, 0},
{ 0, 5, 0,0 } };
TL;DR
you are missing boundary conditions
// Boundary Conditions
if( i == ROW || j == COL || i < 0 || j < 0 )
return false;
Based on the question the matrix is defined as
#define ROW 4
#define COL 4
int grid[ROW][COL] = {{ 4, 11, 1, 1 },
{ 0, 0, 1, 0 },
{ 0, 1, 5, 0},
{ 0, 5, 0,0 } };
given a cell at row i and col j denoted by cordinated i, j the visualization in a 2-D array for that will look like this
i-1, j-1 i-1, j i-1,j+1
i, j-1 i, j i,j+1
i+1, j-1 i+1, j i+1,j+1
from above we can now deduce the corresponding cordinates/points reference to given i,j
i,j ---> North( i-1, j )
i,j ---> South( i+1, j )
i,j ---> East( i , j+1)
i,j ---> West( i , j-1)
now we can write a small function to check if a given value at any cell denoted by i and j is true or not, this below function does similar .. checks if supplied coordinates are within boundary and if the value at grid[j]j] matches what we need to match
bool Check( int grid[ROW][COL], int expected, int i, int j )
{
// Boundary Conditions
if( i == ROW || j == COL || i < 0 || j < 0 )
return false;
return ( grid[i][j] == expected );
}
Now time to put the North, South, West, East calculation to code and expose them as nice functions,
bool northHas( int grid[ROW][COL], int expected, int i, int j )
{
return check(grid, expected, i-1, j );
}
bool southHas( int grid[ROW][COL], int expected, int i, int j )
{
return check(grid, expected, i+1, j );
}
bool eastHas( int grid[ROW][COL], int expected, int i, int j )
{
return check(grid, expected, i, j+1 );
}
bool westHas( int grid[ROW][COL], int expected, int i, int j )
{
return check(grid, expected, i, j-1 );
}
each of these functions above exposes a nicer interface to deal with what logic program wants to do
if( (northHas( grid, 0, i, j ) || northHas( grid, 11, i, j)) &&
( eastHas( grid, 0, i, j ) || eastHas( grid, 11, i, j)) &&
(southHas( grid, 0, i, j ) || southHas( grid, 11, i, j)) &&
( westHas( grid, 0, i, j ) || westHas( grid, 11, i, j)) )
{
return false
}
I have a 2d array like this:
arr = [0 3 1 0
1 2 0 2
0 0 2 0
1 2 0 0]
My aim is don't iterate over a column once we find maximum number in it.
In the first iteration, max number is 3 in 2nd column, so don't go to second column in future iterations.
Similarly in my 2nd iteration, max number is 2 in 4th column (Because we dont go to 2nd column anymore).
This is what i tried:
#include <iostream>
using namespace std;
int main()
{
//Input 2d array
int arr[4][4];
//Take the input
for(int i=0; i<4; i++)
{
for(int j=0; j<4; j++)
cin>>arr[i][j];
}
//Index array to store index of maximum number column
int index[4] = {-1,-1,-1,-1}
//Array to store max number in each row
int max_arr[4] = {0,0,0,0};
for(int i=0; i<4; i++)
{
int max_num = -1;
for(int j=0; j<4; j++)
{
if(j!=index[0] && j!=index[1] && j!=index[2] && j!=index[3])
{
if(max_num<arr[i][j])
{
max_num = arr[i][j];
index[j] = j;
}
}
}
max_arr[i] = max_num;
}
return 0;
}
The best way to go about this is to simply evaluate the array by columns. This can be done with a little math. In your case, you use a 4x4 array. Start at index 0, add 4, add 4, add 4, then subtract 11 (bringing you to position 1). Add 4, add 4, add 4, subtract 11 (bringing you to position 2). Etc...
Here is the code I used, which works and is doable for any size array!
#include <iostream>
int main()
{
constexpr size_t ARR_ROWS = 4;
constexpr size_t ARR_COLS = 4;
constexpr size_t ARR_SIZE = ARR_ROWS * ARR_COLS;
int arr[ARR_SIZE] {
0, 3, 1, 0,
1, 2, 0, 2,
0, 0, 2, 0,
1, 2, 0, 0
};
// Store max values for columns
int cols_max[ARR_COLS] { -1, -1, -1, -1 };
// Start at index 0, then at 4 (3 times) to evaluate first
// column. Next, subtract 11 from current index (12) to get
// to index 1 (start of column 2). Add 4 (3 times) to
// evaluate second column. Next, subtract 11 from current
// index (13) to get to index 2 (start of column 3). Etc...
size_t cur_index = 0;
size_t cur_col = 0;
const size_t subtract_to_start_next_col = ARR_SIZE - (ARR_COLS + 1);
while (cur_index < ARR_SIZE)
{
// Max function for 'cols_max'
if (cols_max[cur_col] < arr[cur_index])
cols_max[cur_col] = arr[cur_index];
if ( // When index is at the column's end (besides last value)
(cur_index >= ARR_SIZE - ARR_COLS) &&
(cur_index <= ARR_SIZE - 2)
)
{
cur_index -= subtract_to_start_next_col;
cur_col++;
}
else if (cur_index == ARR_SIZE - 1)
{ // When index is last value, add 1 to break loop
cur_index++;
}
else
{ // Nothing special, just go to next value in column
cur_index += ARR_COLS;
}
}
// Print columns' max values (optional)...
for (size_t i = 0; i < ARR_COLS; ++i)
{
std::cout
<< "Max for column " << (i + 1) << ": " << cols_max[i]
<< std::endl;
}
}
Feel free to ask if you have any questions!
You need 3 loops, first for iterations, second for rows, third for columns. If you have found max at column let's say 0, then you should blacklist that column and so on.
#include <iostream>
int main()
{
int m[ 4 ][ 4 ] = { { 0, 3, 1, 0 } ,
{ 1, 2, 0, 2 } ,
{ 0, 0, 2, 0 } ,
{ 1, 2, 0, 0 } };
constexpr int max_number_of_itr { 4 };
bool blacklisted[4] { false };
for ( auto itr = 0; itr < max_number_of_itr; ++itr )
{
auto max { -1 };
auto max_col_idx { -1 };
for ( auto row = 0; row < 4; ++row )
{
for ( auto col = 0; col < 4; ++col )
{
if ( blacklisted[ col ] )
continue;
auto val = m[ row ][ col ];
if ( val > max )
{
max = val;
max_col_idx = col;
}
}
}
blacklisted[ max_col_idx ] = true;
std::cout << "max is " << max << " col " << max_col_idx << " ignored." << std::endl;
}
}
index[ j ] = j;
change this to
index[ i ] = j;
I am trying to maximize this function in c++:
I have put this in the function:
int F(int n , int T ){
if( T >= 0 && n == 0){
return 0;
}else if( T < 0){
return INT_MIN;
} else if(T >= 0 && n > 0){
for(int i = 0 ; i <= m[n-1] ; i++){
ganancia = max(i * v[n-1] + F(n-1,T-i*t[n-1]),ganancia );
}
}
}
but when I put on n 3 , T 8, t {1, 2, 2}, v {12, 15, 30} and finally on m{3, 3, 2} my program return 2, when it had to return 99.
You have three branches in the function, but only two return values. If you fail to return a value you will have undefined behavior. You need to return a value from all branches.
Now I have my code like this:
int F(int n , int T ){
if( T >= 0 && n == 0){
return 0;
}else if( T < 0){
return INT_MIN;
} else if(T >= 0 && n > 0){
for(int i = 0 ; i <= m[n-1]-1 ; i++){
return (max(i * v[n-1] + F(n-1,T-i*t[n-1]),(i+1) * v[n-1] + F(n-1,T- (i+1)*t[n-1]) ));
}
}
}
And now it is showing my program 12 instead of 13, at least I have left that 2 value. Thanks!
C++ beginner here. I'm currently trying to make a sudoku solving program, so I have to check whether a value exists in the 9x9 box it's located in.
This is my code for checking if the element follows the rules:
//constants for rows and columns of the sudoku puzzle, can be changed
const int ROWS = 9;
const int COLS = 9;
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value) //check if there are any other values on the same column
return false;
if (grid[i][colIndex] == value) //or the same row
return false;
}
//to-do: check if another equal value exists in the 9x9 box
return true;
}
//returns true if another element has the same value as "value", false otherwise
bool exists_in_2d_array(int grid[ROWS][COLS], int value){
for (int x = 0; x < ROWS / 3; x++)
{
for (int y = 0; y < COLS / 3; y++)
{
if (grid[x][y] == value)
{
return true;
}
}
}
return false;
}
My idea was to find out which 9x9 box the coordinates of the current element lead to, then put that 9x9 grid in another 2D array and check if the element's value exists somewhere else in the grid. I don't really know how, though.
The SUDOKU rules require that the digit is used only once:
Rule 1: in each row
Rule 2: in each column
Rule 3: in each 3x3 subgrid of the 9x9 grid
Function follows_rule() checks for a given grid position, if the value would be allowed or not. For the moment it checks only rules 1 and 2. I propose you the following code for rule 3:
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value)
return false;
if (grid[i][colIndex] == value) // ATTENTION THIS IS OK BECAUSE ROWS==COLS !!
return false;
}
// Check if another equal value exists in the 3x3 box
int sgc = (colIndex / 3) * 3; // in wich subgrid are we ?
int sgr = (rowIndex / 3) * 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (grid[sgr + i][sgc + j] == value)
return false;
return true;
}
You can test the 3x3 verification with the following code:
int sudoku[ROWS][COLS] = {
{ 1, 0, 0, 0, 0, 0, 0, 8, 0 },
{ 0, 0, 2, 0, 0, 0, 0, 0, 0 },
{ 0, 3, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 3, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 5, 0, 0, 0 },
{ 0, 0, 0, 0, 8, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
if (follows_rule(sudoku, 1, 0, 1) == false
&& follows_rule(sudoku, 1, 0, 4) == true
&& follows_rule(sudoku, 5, 5, 8) == false
&& follows_rule(sudoku, 5, 5, 1) == false
&& follows_rule(sudoku, 5, 5, 7) == true)
cout << "Test ok !" << endl;
else cout << "Tests failed" << endl;
Accepted answer does not calculate the subgrids correctly , sgc and and sgr needs to be multiplied with 3 too after division to crrectly identify the subgrid vertices
public boolean isValidEntry(char[][] board, int row , int col,char val)
{
for(int i = 0 ; i < 9 ;i++){
if(board[row][i] == val)
return false;
}
for(int j = 0 ; j < 9 ;j++){
if(board[j][col] == val)
return false;
}
int sgc = col / 3; // in wich subgrid are we ?
int sgr = row / 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
if (board[(3*sgr) + i][(3*sgc) + j] == val)
return false;
}
return true;
}
I'm trying to write a program that creates a matrix of size N, and puts numbers in so that no numbers repeat in the same column/row using backtracking.
1) Put value in cell. If it's a repeat, try a different value.
2) If no such value exists, backtrack 1 cell, and change the value. //recursive
However, the highest number repeats a few times sometimes. E.g:
3 1 2 3 1 2 4 5 2 4 1 3 6 5
1 3 3 2 3 1 5 4 4 3 2 5 1 6
2 3 1 1 2 5 3 5 < 1 5 3 2 4 6
4 5 3 1 2 5 1 6 4 2 3
5 4 5 2 1 < 6 2 4 1 3 6 <
^ 3 6 5 6 6 4 <
^
And here's what it's doing:
Once it runs out of numbers to put into a cell (i.e: all restricted, it puts N in)
3 1 2 4 3 1 2 4 3 1 2 4 3 1 2 4
1 2 3 0 -> 1 2 3 3 -> 1 2 3 4 -> 1 2 3 4
0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
I'm really stuck here, hopefully someone can find the error in my code:
int **grid; //2d dynamic array of size 'size'
bool checkRepeat(size,**grid,row,column); //checks if a number in a column/row is a repeat
int backtrack = 0;
int holder = 0; //when backtracking, this holds the number that should be changed
bool checkRepeat(int x, int** grid, int row, int col){
for (int i = 0; i < x; i++){
if (grid[row][col] == grid[row][i] && col != i){
return true;
}
}
for (int j = 0; j < x; j++){
if (grid[row][col] == grid[j][col] && row != j){
return true;
}
}
return false;
}
int main(){
for (int row = 0; row < size; row++){
for (int col = 0; col < size; col++){
if (backtrack == 0){
grid[row][col] = rand() % size + 1;
}
if (backtrack == 1){ //If backtracking, go back one cell.
grid[row][col] = 0; //(Since the above for loops went one
if (col == 0){ //cell forward, go 2 cells back)
col = size - 2;
row--;
} else if (col == 1){
col = size - 1;
row--;
} else {
col-=2;
}
holder = grid[row][col]; //put the current number into holder to avoid it
backtrack = 0;
}
/*the following checks if the number in the current cell is
a repeat and makes sure the number isn't the same as
before (holder). Then it checks all possible numbers (1 to size)
and puts one that matches the rules. If one is not found,
program backtracks 1 cell*/
if (checkRepeat(size,grid,row,col) && grid[row][col] > 0){
for (int x = 1; x < size+1 && (checkRepeat(x,grid,row,col) || holder == grid[row][col]); x++){
grid[row][col] = x;
}
}
if (grid[row][col] == checkRepeat(size,grid,row,col) || grid[row][col] == holder){
backtrack = 1; //if no valid number was found in the above
grid[row][col] = 0;
}
holder = 0;
}
}
So I may have gone a little overboard on the solution but I thought it was a good challenge for me. The basic idea is that fill(row, col) is a recursive function. First it checks the stopping conditions: if the filled-out part of the grid is not valid (a number is repeated in a row or column) it will return false. It will also return false if there's an attempt to fill outside the grid's size.
If neither stopping condition is met, it will try a value for the grid element and attempt to "fill the rest of the grid" (aka call the fn recursively). It will do those things as long as the "fill rest" operation fails and it hasn't tried all valid values. If it has tried all the valid values and the "fill rest" operation still fails, it resets the value to 0. Finally it returns whether the "fill rest" operation failed or succeeded.
#include <vector>
#include <iostream>
#include <cstdlib>
#include <numeric>
#include <time.h>
#include <string>
#include <sstream>
using std::vector;
// helper for std::accumulate
bool logical_and(bool x, bool y) {
return x & y;
}
class Grid {
public:
typedef int ElementType;
typedef vector< vector<ElementType> > GridElements;
Grid(const int linesize) :
linesize_(linesize)
{
srand(time(NULL));
// resizes to linesize_ rows & columns, with initial values == 0
gridElements_.resize(linesize_, vector<ElementType>(linesize_, 0));
}
// use like this: cout << grid.to_s();
std::string to_s() const {
std::stringstream ss;
for (int row = 0; row < gridElements_.size(); row++) {
for (int col = 0; col < gridElements_[row].size(); col++) {
ss << gridElements_[row][col] << " ";
}
ss << std::endl;
}
ss << std::endl;
return ss.str();
}
// return true if there are no repeated numbers within filled elements in
// rows/columns, false otherwise
bool isValid() const {
// you would also need to write and call a checkSquare method if you're doing a sudoku puzzle
for (int i = 0; i < linesize_; i++) {
if (!isRowValid(i) || !isColValid(i)) {
return false;
}
}
return true;
}
// the recursive function that actually puts values in the grid elements
// max recursion depth (I think) is linesize_^2
bool fill(int row, int col) {
// stopping conditions
if (!isValid()) {
return false;
}
if ((row == linesize_) || (col == linesize_)) {
return true;
}
int nextCol = (col + 1) % linesize_;
int nextRow = row;
if (nextCol < col) {
nextRow++;
}
// keep a record of what numbers have been tried in this element
vector<bool> attemptedNumbers(linesize_ + 1, false);
attemptedNumbers[0] = true;
// We will continue choosing values for gridElements_[row][col]
// as long as we haven't tried all the valid numbers, and as long as
// the rest of the grid is not valid with this choice
int value = 0;
bool triedAllNumbers = false;
bool restOfGridValid = false;
while (!triedAllNumbers && !restOfGridValid) {
while (attemptedNumbers[value]) {
value = rand() % linesize_ + 1;
}
attemptedNumbers[value] = true;
gridElements_[row][col] = value;
// uncomment this for debugging/intermediate grids
//std::cout << to_s();
// triedAllNumbers == true if all the numbers in [1, linesize_] have been tried
triedAllNumbers = std::accumulate(attemptedNumbers.begin(), attemptedNumbers.end(), true, logical_and);
restOfGridValid = fill(nextRow, nextCol);
}
if (triedAllNumbers && !restOfGridValid) {
// couldn't find a valid number for this location
gridElements_[row][col] = 0;
}
return restOfGridValid;
}
private:
// checks that a number is used only once in the row
// assumes that values in gridElements_ are in [1, linesize_]
// return false when the row contains repeated values, true otherwise
bool isRowValid(int row) const {
vector<bool> numPresent (linesize_ + 1, false);
for (int i = 0; i < linesize_; i++) {
int element = gridElements_[row][i];
if (element != 0) {
if (numPresent[element]) {
return false;
}
else {
numPresent[element] = true;
}
}
// don't do anything if element == 0
}
return true;
}
// checks that a number is used only once in the column
// assumes that values in gridElements_ are in [1, linesize_]
// return false when the column contains repeated values, true otherwise
bool isColValid(int col) const {
vector<bool> numPresent (linesize_ + 1, false);
for (int i = 0; i < linesize_; i++) {
int element = gridElements_[i][col];
if (element != 0) {
if (numPresent[element]) {
return false;
}
else {
numPresent[element] = true;
}
}
else {
// if element == 0, there isn't anything left to check, so just leave the loop
break;
}
}
return true;
}
// the size of each row/column
int linesize_;
// the 2d array
GridElements gridElements_;
};
int main(int argc, char** argv) {
// 6x6 grid
Grid grid(6);
// pretty sure this is mathematically guaranteed to always return true, assuming the algorithm is implemented correctly ;)
grid.fill(0, 0);
std::cout << grid.to_s();
}