Meaning of "direction X-Y delta pairs for adjacent cells" - c++

I'm trying to understand the game algorithm called "Boggle"
which finds words in an N*N matrix.
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 6; // max length of a word in the board
char in[N * N + 1]; // max length of a word
char board[N+1][N+2]; // keep room for a newline and null char at the end
char prev[N * N + 1];
bool dp[N * N + 1][N][N];
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
bool visited[N][N];
bool checkBoard(char* word, int curIndex, int r, int c, int wordLen)
{
if (curIndex == wordLen - 1)
{
//cout << "Returned TRUE!!" << endl;
return true;
}
int ret = false;
for (int i = 0; i < 8; ++i)
{
int newR = r + dx[i];
int newC = c + dy[i];
if (newR >= 0 && newR < N && newC >= 0 && newC < N && !visited[newR] [newC] && word[curIndex+1] == board[newR][newC])
I do not understand this part:
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
Why do these array have the values they have and why does this work?

These arrays represent the possible combinations of row and column offsets from the current "cursor" location (which is an x,y coordinate tracked in the code as variables c,r):
// direction X-Y delta pairs for adjacent cells
int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};
int dy[] = {1, 1, 0, -1, -1, -1, 0, 1};
For example, if you imagine a 3x3 square grid, and consider the central box to be the current location, then the other 8 surrounding cells are those indicated by these sets of row and column offsets. If we took the offsets at index 2 (dx[2] = 1 and dy[2] = 0), this would indicate the cell one row down (and zero shifting left/right).

Related

My sudoku backtrack algorithm isn't working after the 7th line. What am I doing wrong?

My code runs but when I try to print the board using a function and when I check if the algorithm had aleast solved the board, it only solves up to the 7th line then stops.
In my process to see what I was doing wrong I printed my board right after the if statement that includes checkforzero in the last function that is initialized. That is how I found out that my code only solves until the seventh line of the puzzle. It also confuses me on how even through I reference the sodoku_board vector it still doesn't output a value of the changed 7 lines after solving it through the algorithm in the main function.
#include<iostream>
#include<vector>
#include<algorithm>
void print_board(std::vector<std::vector<int>> sudoku_board);
std::vector<std::vector<int>> missing_nums(std::vector<std::vector<int>> sudoku_board);
bool check_viable(std::vector<std::vector<int>> sudoku_board, int row, int column, int number);
bool checkforzero(std::vector<std::vector<int>> sudoku_board, int &row, int &column);
bool solve_board(std::vector<std::vector<int>> &sudoku_board, std::vector<std::vector<int>> missing);
int main(){
std::vector<std::vector<int>> missing;
//created board
std::vector<std::vector<int>> sudoku_board = {
{1, 0, 8, 0, 0, 5, 0, 0, 6},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{5, 0, 3, 8, 2, 0, 7, 0, 0},
{2, 0, 0, 1, 5, 0, 9, 0, 8},
{0, 0, 0, 0, 8, 0, 0, 0, 0},
{8, 0, 9, 0, 4, 2, 0, 0, 5},
{0, 0, 5, 0, 9, 8, 2, 0, 4},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{9, 0, 0, 2, 0, 0, 6, 0, 1}
};
print_board(sudoku_board);
missing = missing_nums(sudoku_board);
bool end = solve_board(sudoku_board, missing);
print_board(sudoku_board);
}
//simply printing the board inputed
void print_board(std::vector<std::vector<int>> sudoku_board){
std::cout<<"\n";
for(auto c : sudoku_board){
for(auto d : c){
std::cout<<d<<" ";
}
std::cout<<"\n";
}
std::cout<<"\n";
}
//find the missing nums in each row
std::vector<std::vector<int>> missing_nums(std::vector<std::vector<int>> sudoku_board){
std::vector<std::vector<int>> r(9);
for(int c = 0; c < 9; c++)
for(int i = 1; i <= 9; i++)
if(find(sudoku_board[c].begin(), sudoku_board[c].end(), i) == sudoku_board[c].end())
r[c].push_back(i);
return r;
}
//checks if the number can be inputed on board
bool check_viable(std::vector<std::vector<int>> sudoku_board, int row, int column, int number){
int row_change;
//checks vertical
for(int rowed : sudoku_board[row])if(rowed == number)return false;
//checks horizontal
for(int i = 0; i < sudoku_board.size(); i++)if(sudoku_board[i][column] == number)return false;
//checks box
while(row != 0 && row != 3 && row != 6)row--;
while(column != 0 && column != 3 && column != 6)column--;
for(int v = column; v <= column + 2; v++)if(sudoku_board[row+1][v] == number || sudoku_board[row+2][v] == number || sudoku_board[row][v] == number)return false;
return true;
}
bool checkforzero(std::vector<std::vector<int>> sudoku_board, int &row, int &column){
for(int i = 0; i < 9; i++){
for(int v = 0; v < 9; v++){
if(sudoku_board[i][v] == 0){
row = i;
column = v;
return true;
}
}
}
return false;
}
bool solve_board(std::vector<std::vector<int>> &sudoku_board, std::vector<std::vector<int>> missing){
int row, column;
if(!checkforzero(sudoku_board, row, column))
return true;
print_board(sudoku_board);
for(int d = 0; d < missing[row].size(); d++){
if(check_viable(sudoku_board, row, column, missing[row][d])){
sudoku_board[row][column] = missing[row][d];
if(solve_board(sudoku_board, missing))
return true;
sudoku_board[row][column] = 0;
}
}
return false;
}

OpenCV: create a square Structuring element for HIT-MISS

I want a function to create a "square inside a square" structuring element, like:
Mat explicit_kernel = (Mat_<int>(5, 5) <<
-1, -1, -1, -1, -1,
-1, 1, 1, 1, -1,
-1, 1, 1, 1, -1,
-1, 1, 1, 1, -1,
- 1, -1, -1, -1, -1);
So I tried to make an ugly loop:
Mat generate_kernel(int size)
{
if (size % 2 == 0)
{
printf("Input %i, not even, replaced by %i\n", size, size + 1);
size++;
}
Mat out = Mat::ones(size + 2, size + 2, CV_8S);
for (int i = 0; i <= size + 1; i++)
{
for (int j = 0; j <= size + 1; j++)
{
if (i == 0 || i == size - 1)
{
out.at<int>(i, j) = -1;
}
else
{
if (j == 0 || j == size - 1)
{
out.at<int>(i, j) = -1;
}
}
}
}
//Mat out = getStructuringElement(MORPH_RECT, Size(size, size), Point(-1, -1));
return out;
}
But I got an "Violation writting error", and anyway Im looking for an easier want,
The main purpose of the code is to make structuring element inside a loop:
- squares of size 1, size 3 ...
Thanks :)
I found a solution, considering that cv::Mat is a pointer, and creating a sub Matrix
Mat generate_kernel(int size)
{
if (size % 2 == 0)
{
printf("Input %i, not even, replaced by %i\n", size, size + 1);
size++;
}
Mat out = -1 * Mat::ones(size + 2, size + 2, CV_8S);
Mat center = Mat(out, Rect(1, 1, size, size));
center = Mat::ones(size, size, CV_8S);
return out;
}
This might already be handled by the cv::copyMakeBorder method.
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat generate_kernel(int size, int outer_size=1)
{
if (size % 2 == 0)
{
printf("Input %i, not even, replaced by %i\n", size, size + 1);
size++;
}
Mat out = Mat::ones(size, size, CV_8S);
copyMakeBorder(out,
out,
outer_size, // top
outer_size, // bottom
outer_size, // left
outer_size, // right
BORDER_CONSTANT,
Scalar(-1.0));
return out;
}
int main(int argc, const char * argv[]) {
cout << "Size 1: " << generate_kernel(1) << endl;
cout << "Size 3: " << generate_kernel(3) << endl;
cout << "Size 5: " << generate_kernel(5) << endl;
return 0;
}
Which would generate the following....
Size 1: [ -1, -1, -1;
-1, 1, -1;
-1, -1, -1]
Size 3: [ -1, -1, -1, -1, -1;
-1, 1, 1, 1, -1;
-1, 1, 1, 1, -1;
-1, 1, 1, 1, -1;
-1, -1, -1, -1, -1]
Size 5: [ -1, -1, -1, -1, -1, -1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, 1, 1, 1, 1, 1, -1;
-1, -1, -1, -1, -1, -1, -1]

converting an array of integers to string

If I have an array that looks like
int digits[size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4}
I want to remove the leading zeros and to do so I'm attempting to convert the array of integers into a string (which is an array of chars).
My attempt looks like
string toString(int digits[], int size){
string number = " ";
for(int i = 0; i < size - 1; i++){
number[i] = digits[i];
}
return number;
}
which came out horribly broken.
I also can't simply remove all zeros, just the leading ones.
Also if I may dogpile another question here:
how can I identify if a string is numeric?
e.g
string number = "12a4"
cout << "not a number"
you can use C++11 function std::to_string() here is an example
#include <string>
#include <iostream>
int main()
{
int size = 15;
int digits[size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
std::string result = "";
for (int i = 0; i < size; i++)
{
if (!(digits[i] == 0 && result.size() == 0))
result += std::to_string(digits[i]);
}
std::cout << result << std::endl;
}
you can check if a string is numeric using this function
bool isNb(std::string str)
{
if (str.size() == 0)
return false;
for (int i = 0; i < str.size(); i++)
{
if (std::isdigit(str.at(i)) == false)
return false;
}
return true;
}
Instead of changing digits with your for loop, add them with
number += to_string(digits[i]);
Also, you can remove the toString line you have, and just use it as I put here.
As to your other question, just use a for loop to check each digit in the string and its ASCII value, if there is any whose ASCII value is less than 48 or greater than 57 then it's not a number.
Try the following way:
int i = 0;
while(digits[i] == 0) i++;
for (; i < size; i++)
result += to_string(digits[i]);
To answer your actual question (How to remove the leading zeros?) here a solution without strings:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
std::vector<int> x = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
// ...or if you insist on the array...
// int x[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
// std::vector<int> x = {x,x+15};
auto it = std::find_if_not(x.begin(),x.end(),[](int i){return i==0;});
std::vector<int> y{it,x.end()};
for (auto i : y) std::cout << i << " ";
}
prints:
1 2 3 0 4
You can use a string stream to convert from any type to string:
#include <sstream> //<-- ALLOWS USE OF std::stringstream
const int size = 15;
int digits[size] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 4};
std::stringstream ss; //<-- DECLARE STREAM
int k;
for (k = 0; k < size; ++k)
if (digits[k] != 0)
break; //FIND FIRST NON-0 INDEX
for (int i = k; i < size; ++i)
ss << digits[i]; //ADD TO THE STREAM s
std::cout<< ss.str() << std::endl; //PRINT STREAM
12304

How do you find out in which sub-grid a 2D array element is located

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;
}

Find largest area in 2d array in c++

I need to write recursive function in c++ that finds largest area of number '1' in 2d array that contains only 1 or 0.
Example:
int Arr[5][8] =
{
{ 0, 0, 0, 0, 1, 1, 0, 0, },
{ 1, 0, 0, 1, 1, 1, 0, 0, },
{ 1, 1, 0, 1, 0, 1, 1, 0, },
{ 0, 0, 0, 1, 1, 1, 1, 0, },
{ 0, 1, 1, 0, 0, 0, 0, 0, },
};
Visual example: http://s23.postimg.org/yabwp6h23/find_largest.png
Largest area of this array is 12, second largest is 3 and third largest is 2.
I was thinking to do this with something similar to flood fill algorithm, but just can't figure out how.
bool visited[5][8];
int i,j;
// variables for the area:
int current_area = 0, max_area = 0;
int Arr[5][8]={ // type your map of values here
}
// functions
void prepare_visited_map() {
for(i=0;i<5;i++) {
for(j=0;j<8;j++) visited[i][j] = false;
}
}
// recursive function to calculate the area around (x,y)
void calculate_largest_area(int x, int y) {
if(visited[x][y]) return;
// check if out of boundaries
if(x<0 || y<0 || x>=5 || y>=8) return;
// check if the cell is 0
if(!Arr[x][y]) {
visited[x][y] = true;
return;
}
// found a propper cell, proceed
current_area++;
visited[x][y] = true;
// call recursive function for the adjacent cells (north, east, south, west)
calculate_largest_area(x,y-1);
calculate_largest_area(x+1,y);
calculate_largest_area(x,y+1);
calculate_largest_area(x-1,y);
// by the end of the recursion current_area will hold the area around the initial cell
}
// main procedure where the above functions are used
int mian() {
// calculate the sorrounding area of each cell, and pick up the largest of all results
for(i=0;i<5;i++) {
for(j=0;j<8;j++) {
prepare_visited_map();
calculate_largest_area(i,j);
if(current_area > max_area) max_area = current_area;
}
}
printf("Max area is %d",max_area");
}
Hope this was helpful :)
I was thinking to do this with something similar to flood fill algorithm
I think that's a pretty good way to do it. Apply flood fill to any 1, counting the ones and replacing them with zeros.
Repeat until the grid consists entirely of zeroes.
The following will print out the sizes of the connected components in no particular order:
#include <iostream>
constexpr int N = 5;
constexpr int M = 8;
int arr[N][M] =
{
{ 0, 0, 0, 0, 1, 1, 0, 0, },
{ 1, 0, 0, 1, 1, 1, 0, 0, },
{ 1, 1, 0, 1, 0, 1, 1, 0, },
{ 0, 0, 0, 1, 1, 1, 1, 0, },
{ 0, 1, 1, 0, 0, 0, 0, 0, },
};
int fill(int arr[N][M], int r, int c) {
int count = 0;
if (r < N && arr[r][c]) {
for (int i = c; i >= 0 && arr[r][i]; --i) {
arr[r][i] = 0;
count += fill(arr, r + 1, i) + 1;
}
for (int i = c + 1; i < M && arr[r][i]; ++i) {
arr[r][i] = 0;
count += fill(arr, r + 1, i) + 1;
}
}
return count;
}
int print_components(int arr[N][M]) {
for (int r = 0; r < N; ++r) {
for (int c = 0; c < M; ++c) {
if (arr[r][c]) {
std::cout << fill(arr, r, c) << std::endl;
}
}
}
}
int main() {
print_components(arr);
}
something like,
int max_area = 0;
foreach y
foreach x
if (pos[y][x] == 1 && !visited[y][x])
{
int area = 0;
Queue queue = new Queue();
queue.push(new Point(x, y));
visited[y][x] = true;
while (!queue.empty())
{
Point pt = queue.pop();
area++;
foreach neightboor of pt (pt.x±1, pt.y±1)
if (pos[neightboor.y][neightboor.x] == 1 && !visited[neightboor.y][neightboor.x])
{
visited[neightboor.y][neightboor.x] = true;
queue.push(new Point(neightboor.x, neightboor.y));
}
}
if (area > max_area)
max_area = area;
}
Quick approach, but I don't know if there is a way to do this in a sane way (recursive
call for each element does not scale for C++ because call stack is limited)
int maxy = 5
int maxx = 8
int areasize(int x, int y) {
if (x < 0 || y < 0 || x > maxx || y > maxy || !Arr[y][x])
return 0;
Arr[y][x] = 0;
return 1
+ areasize(x + 1, y)
+ areasize(x - 1, y)
+ areasize(x, y + 1)
+ areasize(x, y - 1);
}
maxarea = 0;
for (int y = 0; y < maxy; y++) {
for (int x = 0; x < maxx; x++) {
maxarea = std::max(maxarea, areasize(x, y));
}
}