I am given a square matrix size n and characters that the matrix contains.
For example:
3
one
two
row
I have to rotate the matrix by 45 degrees.
| | |o| | |
|o|n|e| | |t| |n| |
|t|w|o| -> |r| |w| |e|
|r|o|w| | |o| |o| |
| | |w| | |
I get
| | |o| | |
|o|n|e| | |t| |n| |
|t|w|o| -> |r| |w| |e|
|r|o|w| | |o|w|o| |
| | | | | |
This is due to rounding values.
I wrote the code. My solution is very limited, I represent it only to show the Idea and my mistakes.
The main thing I don't understand is how to store characters in array so that they have right place (coordinates x, y) after rounding floating point values to integer values. Is there a proper way of doing it?
Are there any advices or observations?
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cmath>
struct Coordinates
{
int x, y;
};
int main()
{
int n;
std::ifstream fin("U3.txt");
fin >> n;
fin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::vector<std::vector<char>> matrix;
for (int i = 0; i < n; i++)
{
std::string temp_s;
std::vector<char> temp_v(n);
std::getline(fin, temp_s, '\n');
for (int j = 0; j < n; j++)
{
temp_v[j] = temp_s[j];
}
matrix.push_back(temp_v);
}
fin.close();
std::vector<Coordinates> cord(n * n); // Store coordinates after rotation
int index = 0;
for (int y = 0; y < n; y++)
{
for (int x = 0; x < n; x++)
{
// Multiplying two matrices
/*
[ cos(45) -sin(45) ] [ x ]
[ sin(45) con(45) ] [ y ]
=
[ sqrt(2)/2 -sqrt(2)/2 ] [ x ]
[ sqrt(2)/2 sqrt(2)/2 ] [ y ]
=
[ sqrt(2)/2 * (x - y) ]
[ sqrt(2)/2 * (x + y) ]
*/
double new_x = (std::sqrt(2) / 2 * (x - y));
double new_y = (std::sqrt(2) / 2 * (x + y));
// Trying to round value to int because the index of array is int
cord[index].x = (new_x >= 0.0 ? std::ceil(new_x) : std::floor(new_x));
cord[index].y = (new_y >= 0.0 ? std::ceil(new_y) : std::floor(new_y));
index++;
}
}
/*
Finding the min_x and min_y to know how much should I add to
the new x and y coordinates to keep the coordinates positive,
as I have to store them in array.
*/
int min_x = std::numeric_limits<int>::max();
int min_y = std::numeric_limits<int>::max();
for (int i = 0; i < n * n; i++)
{
if (min_x > cord[i].x) { min_x = cord[i].x; }
if (min_y > cord[i].y) { min_y = cord[i].y; }
}
// If there are no negative coordinates then there is nothing to add
// So I initialize min_x and min_y to 0
if (min_x >= 0) { min_x = 0; }
if (min_y >= 0) { min_y = 0; }
std::vector<std::vector<char>> new_matrix(10, std::vector<char>(10, ' '));
int row = 0, column = 0;
for (int i = 0; i < cord.size(); i++)
{
new_matrix[cord[i].y + min_y * (-1)][cord[i].x + min_x * (-1)] = matrix[row][column];
if ((i + 1) % n == 0) { row++; column = 0; continue; }
column++;
}
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
std::cout << new_matrix[i][j];
}
std::cout << std::endl;
}
return 0;
}
Hm, in my understanding, your algorithm using a rotation matrix will not work. You will always have problems with rounding. And with the correct placement of the values at the correct position in the destination matrix.
And it is even not needed, because the indices for the 2 dimensional can be calculated really simply, without any float operation.
To find a better approach, let us first analyse the possible data:
As you can see. The "next value" of an original row, has to be placed always one to the right and one down. So, for n=3. Print 1, goto right, go down, print 2, goto right, go down. And so on.
If a new source row starts, then the destination start row and start column, are the above value, but then one left and one down. And then again the same as above. Right, down, right, down. And so on and so on.
So, very simple.
Then, the size of the new matrix is always 2*n-1, because we will always have a space between 2 characters.
The destination start row is of course also 0 and the destination start column is simply n-1.
All indices are of course 0 based.
With that approach, no shifting is necessary. Target values can be placed at the correct coordinates immediately.
The solution is then straightforward:
#include <string>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <iterator>
const std::string sourceFileName{ "U3.txt" };
int main() {
// Open the source File and check, if it could be opened
if (std::ifstream sourceFileStream{ sourceFileName }; sourceFileStream) {
// Read the size of the matrix (Must be > 0). Eat trailing white spaces
if (size_t matrixSize{}; (sourceFileStream >> matrixSize >> std::ws) and (matrixSize > 0)) {
// Read the complete source file
std::vector sourceRow(std::istream_iterator<std::string>(sourceFileStream), {});
// Define a 2 dim vector for target. Size is 2*n-1
std::vector<std::vector<char>> destination(matrixSize*2-1, std::vector<char>(matrixSize*2-1, ' '));
// Set start indices for destination. Please note: XStart, or Column start is always matrixSize-1
size_t startOffsetIndexDestinationColumn{ matrixSize - 1 };
size_t startOffsetIndexDestinationRow{};
// Iterate over all source rows
for (size_t row{}; (row < matrixSize) and (row < sourceRow.size()); ++row) {
// Calculate offset for coordinates in destination table
size_t offsetRow{ startOffsetIndexDestinationRow };
size_t offsetColumn{ startOffsetIndexDestinationColumn - row};
// Iterate over source columns in rows and assign value to calculated destination coordinates
for (size_t column{}; (column < matrixSize) and (column < sourceRow[row].size()); ++column) {
// Assign value
destination[row + offsetRow++][column + offsetColumn] = sourceRow[row][column];
}
}
// Show result to user. For each row in the destination vector
for (const auto& row : destination) {
// And for each column in this row
for (const char c : row) std::cout << c;
// Next row
std::cout << '\n';
}
}
else std::cerr << "\nError: Wrong dimension in source file ' " << sourceFileName << "'\n";
}
else std::cerr << "\nError: Could not open source file '" << sourceFileName << "'\n";
return 0;
}
So, selecting the proper algorithm will save you a lot of headaches.
Related
I want to make a maze in C++, however I keep running into a problem with the right outer wall. I was wondering if you guys know a way so I can make the outer wall. Ive been trying to work from up to down using \n, but when \n is used the next symbol just goes to the left wall. Thanks in advance!
#include <iostream>
#include <vector>
#include <stack>
/* class Maze {
public:
void makeMaze();
void Print() const;
private:
std::vector <std::vector <char>> Maze;
}; */
int main(int argc, char* argv[]) {
const int WIDTH = 4;
const int HEIGHT = 4;
/* std::string seedValue = " ";
HEIGHT = atoi(argv[1]);
WIDTH = atoi(argv[2]);
if (argc > 3) {
seedValue = argv[3];
} */
// row, column
std::vector <std::vector <std::string>> Maze (WIDTH + 1, std::vector<std::string> (HEIGHT + 1));
// Roof
for (int column = 0; column < WIDTH; column++) {
Maze[0][column] = "+---";
}
// Left Wall
for (int row = 1; row < HEIGHT + 1; row++) {
Maze[row][0] = "|\n+";
}
// Floor
for (int i = 1; i < WIDTH + 1; i++) {
Maze[HEIGHT][i] = "---+";
}
// Right Wall
// FIXME
// Print Maze
for (int i = 0; i < Maze.size(); i++) {
for (int j = 0; j < Maze.at(0).size(); j++) {
std::cout << Maze[i][j];
}
std::cout << std::endl;
}
}
You may want to treat your printable maze as a matrix of chars instead of strings:
You can consider each cell of the maze border having a horizontal fill +--- and a vertical fill +|, and a cell_width and cell_height.
Your maze would be then defined as a matrix of chars sized maze_height * cell_height + 1 and maze_width * cell_width + 1. That extra one is needed for the right and bottom borders.
In order to fill the border, you can define two helper functions, fill_horizontal_border_cell and fill_vertical_border_cell. These functions just copy the contents of the strings horizontal_border_fill and vertical_border_fill respectively to the maze matrix.
Finally, you'd need to separately fill the bottom left border corner.
All this code should be properly encapsulated into classes (e.g. MazeView for the printable maze, MazeBorderView for the printable maze border, and so on).
[Demo]
#include <iostream> // cout
#include <string>
#include <vector>
int main(int argc, char* argv[]) {
// Border
const std::string horizontal_border_fill{"+---"};
const std::string vertical_border_fill{"+|"};
auto cell_width{horizontal_border_fill.size()};
auto cell_height{vertical_border_fill.size()};
// Maze
const size_t maze_width = 6;
const size_t maze_height = 5;
std::vector<std::vector<char>> maze(maze_height * cell_height + 1,
std::vector<char>(maze_width * cell_width + 1, ' ')); // + 1 for the right and bottom borders
// Fill border
auto fill_horizontal_border_cell = [&maze, &horizontal_border_fill, &cell_width, &cell_height](size_t row, size_t col) {
row *= cell_height;
col *= cell_width;
for (auto& c : horizontal_border_fill) { maze[row][col++] = c; }
};
auto fill_border_vertical_cell = [&maze, &vertical_border_fill, &cell_width, &cell_height](size_t row, size_t col) {
row *= cell_height;
col *= cell_width;
for (auto& c : vertical_border_fill) { maze[row++][col] = c; }
};
for (size_t col{0}; col < maze_width; ++col) { // horizontal borders
fill_horizontal_border_cell(0, col); // top
fill_horizontal_border_cell(maze_height, col); // bottom
}
for (size_t row{0}; row < maze_height; ++row) { // vertical borders
fill_border_vertical_cell(row, 0); // top
fill_border_vertical_cell(row, maze_width); // bottom
}
maze[maze_height * cell_height][maze_width * cell_width] = horizontal_border_fill[0]; // bottom left border corner
// Print maze
for (size_t row{0}; row < maze.size(); ++row) {
for (size_t col{0}; col < maze[0].size(); ++col) {
std::cout << maze[row][col];
}
std::cout << "\n";
}
}
// Outputs:
//
// +---+---+---+---+---+---+
// | |
// + +
// | |
// + +
// | |
// + +
// | |
// + +
// | |
// +---+---+---+---+---+---+
You can keep your current implementation for the most part. The only issue is \n. Do not have any of those, they are not needed and will only give you problems. Your std::cout << std::endl; makes a new line after each row, that's all you need. So, do not include \n in neither the left, nor the right wall
To also "create" the right wall, you can copy what you did for the left wall, but with some minor adjustments:
// Right wall
for (int row = 1; row < HEIGHT + 1; row++) {
Maze[row][WIDTH] = "|";
}
Also, what are the pluses for? (+)
You don't have to merge the strings together in order to make it work. Your std::cout << Maze[i][j]; simply adds each string to end of the previous, until you send the endl to make a new line.
So, I would say get rid of the pluses, (unless it is for styling).
The left wall should look like this:
// Left Wall
for (int row = 1; row < HEIGHT + 1; row++) {
Maze[row][0] = "|";
}
I recently finished making an algorithm for a project I'm working on.
Briefly, a part of my project needs to fill a matrix, the requirements of how to do it are these:
- Fill the matrix in form of spiral, from the center.
- The size of the matrix must be dynamic, so the spiral can be large or small.
- Every two times a cell of the matrix is filled, //DO STUFF must be executed.
In the end, the code that I made works, it was my best effort and I am not able to optimize it more, it bothers me a bit having had to use so many ifs, and I was wondering if someone could take a look at my code to see if it is possible to optimize it further or some constructive comment (it works well, but it would be great if it was faster, since this algorithm will be executed several times in my project). Also so that other people can use it!
#include <stdio.h>
typedef unsigned short u16_t;
const u16_t size = 7; //<-- CHANGE HERE!!! just odd numbers and bigger than 3
const u16_t maxTimes = 2;
u16_t array_cont[size][size] = { 0 };
u16_t counter = 3, curr = 0;
u16_t endColumn = (size - 1) / 2, endRow = endColumn;
u16_t startColumn = endColumn + 1, startRow = endColumn + 1;
u16_t posLoop = 2, buffer = startColumn, i = 0;
void fillArray() {
if (curr < maxTimes) {
if (posLoop == 0) { //Top
for (i = buffer; i <= startColumn && curr < maxTimes; i++, curr++)
array_cont[endRow][i] = counter++;
if (curr == maxTimes) {
if (i <= startColumn) {
buffer = i;
} else {
buffer = endRow;
startColumn++;
posLoop++;
}
} else {
buffer = endRow;
startColumn++;
posLoop++;
fillArray();
}
} else if (posLoop == 1) { //Right
for (i = buffer; i <= startRow && curr < maxTimes; i++, curr++)
array_cont[i][startColumn] = counter++;
if (curr == maxTimes) {
if (i <= startRow) {
buffer = i;
} else {
buffer = startColumn;
startRow++;
posLoop++;
}
} else {
buffer = startColumn;
startRow++;
posLoop++;
fillArray();
}
} else if (posLoop == 2) { //Bottom
for (i = buffer; i >= endColumn && curr < maxTimes; i--, curr++)
array_cont[startRow][i] = counter++;
if (curr == maxTimes) {
if (i >= endColumn) {
buffer = i;
} else {
buffer = startRow;
endColumn--;
posLoop++;
}
} else {
buffer = startRow;
endColumn--;
posLoop++;
fillArray();
}
} else if (posLoop == 3) { //Left
for (i = buffer; i >= endRow && curr < maxTimes; i--, curr++)
array_cont[i][endColumn] = counter++;
if (curr == maxTimes) {
if (i >= endRow) {
buffer = i;
} else {
buffer = endColumn;
endRow--;
posLoop = 0;
}
} else {
buffer = endColumn;
endRow--;
posLoop = 0;
fillArray();
}
}
}
}
int main(void) {
array_cont[endColumn][endColumn] = 1;
array_cont[endColumn][endColumn + 1] = 2;
//DO STUFF
u16_t max = ((size * size) - 1) / maxTimes;
for (u16_t j = 0; j < max; j++) {
fillArray();
curr = 0;
//DO STUFF
}
//Demostration
for (u16_t x = 0; x < size; x++) {
for (u16_t y = 0; y < size; y++)
printf("%-4d ", array_cont[x][y]);
printf("\n");
}
return 0;
}
Notice that the numbers along the diagonal (1, 9, 25, 49) are the squares of the odd numbers. That's an important clue, since it suggests that the 1 in the center of the matrix should be treated as the end of a spiral.
From the end of each spiral, the x,y coordinates should be adjusted up and to the right by 1. Then the next layer of the spiral can be constructed by moving down, left, up, and right by the same amount.
For example, starting from the position of the 1, move up and to the right (to the position of the 9), and then form a loop with the following procedure:
move down, and place the 2
move down, and place the 3
move left, and place the 4
move left, and place the 5
etc.
Thus the code looks something like this:
int size = 7;
int matrix[size][size];
int dy[] = { 1, 0, -1, 0 };
int dx[] = { 0, -1, 0, 1 };
int directionCount = 4;
int ringCount = (size - 1) / 2;
int y = ringCount;
int x = ringCount;
int repeatCount = 0;
int value = 1;
matrix[y][x] = value++;
for (int ring = 0; ring < ringCount; ring++)
{
y--;
x++;
repeatCount += 2;
for (int direction = 0; direction < directionCount; direction++)
for (int repeat = 0; repeat < repeatCount; repeat++)
{
y += dy[direction];
x += dx[direction];
matrix[y][x] = value++;
}
}
I saw already many approaches for doing a spiral. All a basically drawing it, by following a path.
BUT, you can also come up with an analytical calculation formula for a spiral.
So, no recursion or iterative solution by following a path or such. We can directly calculate the indices in the matrix, if we have the running number.
I will start with the spiral in mathematical positive direction (counter clockwise) in a cartesian coordinate system. We will concentrate on X and Y coordinates.
I made a short Excel and derived some formulas from that. Here is a short picture:
From the requirements we know that the matrix will be quadratic. That makes things easier. A little bit trickier is, to get the matrix data symmetrical. But with some simple formulas, derived from the prictures, this is not really a problem.
And then we can calculate x and y coordinates with some simple statements. See the below example program with long variable names for better understanding. The code is made using some step by step approach to illustrate the implementation. Of course it can be made more compact easily. Anyway. Let's have a look.
#include <iostream>
#include <cmath>
#include <iomanip>
int main() {
// Show some example values
for (long step{}; step < 81; ++step) {
// Calculate result
const long roundedSquareRoot = std::lround(std::sqrt(step));
const long roundedSquare = roundedSquareRoot * roundedSquareRoot;
const long distance = std::abs(roundedSquare - step) - roundedSquareRoot;
const long rsrIsOdd = (roundedSquareRoot % 2);
const long x = (distance + roundedSquare - step - rsrIsOdd) / (rsrIsOdd ? -2 : 2);
const long y = (-distance + roundedSquare - step - rsrIsOdd) / (rsrIsOdd ? -2 : 2);
// Show ouput
std::cout << "Step:" << std::setw(4) << step << std::setw(3) << x << ' ' << std::setw(3) << y << '\n';
}
}
So, you see that we really have an analytical solution. Given any number we can calculate the x and y coordinate using a formula. Cool.
Getting indices in a matrix is just adding some offset.
With that gained know how, we can now easily calculate the complete matrix. And, since there is no runtime activity needed at all, we can let the compiler do the work. We will simply use constexpr functions for everything.
Then the compiler will create this matrix at compile time. At runtime, nothing will happen.
Please see a very compact solution:
#include <iostream>
#include <iomanip>
#include <array>
constexpr size_t MatrixSize = 15u;
using MyType = long;
static_assert(MatrixSize > 0 && MatrixSize%2, "Matrix size must be odd and > 0");
constexpr MyType MatrixHalf = MatrixSize / 2;
using Matrix = std::array<std::array<MyType, MatrixSize>, MatrixSize >;
// Some constexpr simple mathematical functions ------------------------------------------------------------------------------
// No need for <cmath>
constexpr MyType myAbs(MyType v) { return v < 0 ? -v : v; }
constexpr double mySqrtRecursive(double x, double c, double p) {return c == p? c: mySqrtRecursive(x, 0.5 * (c + x / c), c); }
constexpr MyType mySqrt(MyType x) {return (MyType)(mySqrtRecursive((double)x,(double)x,0.0)+0.5); }
// Main constexpr function will fill the matrix with a spiral pattern during compile time -------------------------------------
constexpr Matrix fillMatrix() {
Matrix matrix{};
for (int i{}; i < (MatrixSize * MatrixSize); ++i) {
const MyType rsr{ mySqrt(i) }, rs{ rsr * rsr }, d{ myAbs(rs - i) - rsr }, o{ rsr % 2 };
const size_t col{ (size_t)(MatrixHalf +((d + rs - i - o) / (o ? -2 : 2)))};
const size_t row{ (size_t)(MatrixHalf -((-d + rs - i - o) / (o ? -2 : 2)))};
matrix[row][col] = i;
}
return matrix;
}
// This is a compile time constant!
constexpr Matrix matrix = fillMatrix();
// All the above has been done during compile time! -----------------------------------------
int main() {
// Nothing to do. All has beend done at compile time already!
// The matrix is already filled with a spiral pattern
// Just output
for (const auto& row : matrix) {
for (const auto& col : row) std::cout << std::setw(5) << col << ' '; std::cout << '\n';
}
}
Different coordinate systems or other spiral direction can be adapted easily.
Happy coding.
Link of Question : https://www.codechef.com/JULY20B/problems/PTMSSNG
Question Statement
Chef has N axis-parallel rectangles in a 2D Cartesian coordinate system. These rectangles may intersect, but it is guaranteed that all their 4N vertices are pairwise distinct.
Unfortunately, Chef lost one vertex, and up until now, none of his fixes have worked (although putting an image of a point on a milk carton might not have been the greatest idea after all…). Therefore, he gave you the task of finding it! You are given the remaining 4N−1 points and you should find the missing one.
Can anyone suggest where I'm going wrong or update my code or share a few test cases.
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#define ll long long
using namespace std;
int main()
{
int t;
cin >> t;
for (int i = 0; i < t; i++)
{
vector<pair<ll, ll>> v;
ll n, m, a;
bool checkx = false;
cin >> n;
m = 4 * n - 1;
ll x[m], y[m];
ll c, d;
a = (m - 1) / 2;
for (ll i = 0; i < m; i++)
{
cin >> x[i] >> y[i];
v.push_back(make_pair(x[i], y[i]));
}
sort(v.begin(), v.end());
for (ll i = a; i >= 1; --i)
{
if (v[2 * i].first != v[2 * i - 1].first)
{
c = v[2 * i].first;
checkx = true;
if ((2 * i) % 4 == 0 && i >= 2)
{
if (v[2 * i].second == v[2 * i + 1].second)
{
d = v[2 * i + 2].second;
}
else
{
d = v[2 * i + 1].second;
}
}
else
{
if (v[2 * i].second != v[2 * i - 1].second)
{
d = v[2 * i - 1].second;
}
else
{
d = v[2 * i - 2].second;
}
}
break;
}
}
if (checkx)
{
cout << c << " " << d;
}
else
{
if (v[0].second == v[1].second)
{
d = v[2].second;
}
else
{
d = v[1].second;
}
cout << v[0].first << " " << d;
}
cout << endl;
}
return 0;
}
You don't need to do such complex things. Just input your x and y vectors and xor every element of each vector. The final value will be the required answer.
LOGIC :
(a,b)------------------(c,b)
| |
| |
| |
| |
(a,d)------------------(c,d)
See by this figure, each variable (a, b, c, d) occurs even number of times. This "even thing" will also be true for the N rectangles. Hence, you have to find the values of x and y which are occurring odd number of times.
To find the odd one out in such cases, the best trick is to xor every element of the vector. This works because of these properties of xor : k xor k = 0 and k xor 0 = k.
CODE:
#include <functional>
#include <iostream>
#include <numeric>
#include <vector>
signed main() {
std::size_t t, n;
std::cin >> t;
while (t--) {
std::cin >> n;
n = 4 * n - 1;
std::vector<int> x(n), y(n);
for (std::size_t i = 0; i < n; ++i)
std::cin >> x.at(i) >> y.at(i);
std::cout << std::accumulate(x.begin(), x.end(), 0L, std::bit_xor<int>()) << ' '
<< std::accumulate(y.begin(), y.end(), 0L, std::bit_xor<int>()) << '\n';
}
return 0;
}
here is a test case that your code doesn't work:
1
2
1 1
1 4
4 6
6 1
9 6
9 3
4 3
the output of your code is (6,3),but it should be (6,4).
I guess you can check more cases where the rectangles intersects.
from functools import reduce
for _ in range(int(input())):
n=int(input())
li=[]
li1=[]
for i in range(4*n-1):
m,n=map(int,input().split())
li.append(m)
li1.append(n)
r =reduce(lambda x, y: x ^ y,li)
print(r,end=' ')
r =reduce(lambda x, y: x ^ y,li1)
print(r,end=' ')
print()
Hey so I want to create a text version of minesweeper. I created a grid that outputs ones and zeros(mines are represented by 0 and anything that is not a mine is a 1). How would I go about checking how many mines are around each non-mine (or how many 0's are around each number 1). Then updating the numbers to show how many mines are adjacent to them.
If someone could at least tell me where to start I would appreciate it :)
#include "pch.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
string mystring;
int grid[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}
};
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
int rNum = (rand() % 10) + 1;
if (rNum == 1 || rNum == 2)
{
grid[i][j] = 0; // mines are 0
}
else grid[i][j] = 1; // non-mines are represented by 1
std::cout << setw(4) << grid[i][j] << setw(4);
}
std::cout << std::endl;
}
}
I did a very similar thing in Java; although instead of representing the bombs with 0s I used 9s, because it is possible for a non-mine to be surrounded by 0 mines, it is not possible for one to be surrounded by 9 or higher mines. Here is my method:
for(int x = 0; x < 5; x++) {
for(int y = 0; y < 5; y++) {
if(grid[x][y] != 9) {
byte count = 0;
for(int lx = -1; lx <= 1; lx++) { //think of lx and ly as temporary x y
if((x+lx) >= 0 && (x+lx) < 5) {
for(int ly = -1; ly <= 1; ly++) {
if((y+ly) >= 0 && (y+ly) <5) {
if(grid[x+lx][y+ly] == 9) {
count += 1;
}
}
}
}
}
grid[x][y] = count;
}
}
}
Basically what it does is it scrolls through each point on the grid, checking if it is a bomb. If it is not, it checks each of the 8 squares touching it(as long as they are in the bounds of the grid, don't want an undefined index error). Then if they are a bomb it adds one to the count. Finally, it sets the number on the tile equal to the count of touching bombs.
In my case I pass pointer to 2d array of type wchar_t but can be any type as you want. Assuming that you have 2d array, you can refer to each cell by [X,Y] but also you need to check if the cell have all neighbours (for example left top cell of table have only 3 neighbours):
void getNeighbours(wchar_t* scr,int x, int y)
{
// Left
if((x-1)>=0)
{
// value = scr[getIndex(x-1,y)];
}
// Right
if((x+1)<tableWidth)
{
// value = scr[getIndex(x+1,y)];
}
//Up
if((y-1)>=0)
{
// value = scr[getIndex(x,y-1)];
}
//Down
if((y+1)<tableHeight)
{
// value = scr[getIndex(x,y+1)];
}
// Left down
if((x-1)>=0 && ((y-1)>=0))
{
// value = scr[getIndex(x-1,y+1)];
}
// Right Down
if((x+1)<tableWidth && (y+1)<tableHeight)
{
// value = scr[getIndex(x+1,y+1)];
}
// Right UP
if((x+1)<tableWidth && (y-1)>=0)
{
// value = scr[getIndex(x+1,y-1)];
}
// Left Up
if((x-1)>=0 && (y-1)>=0)
{
// value = scr[getIndex(x-1,y-1)];
}
}
getIndex() function to get index of cell indicated by [X,Y]:
int getIndex(int x, int y)
{
return (tableWidth*y+x);
}
I'm trying to solve one problem, which I found on website https://open.kattis.com/problems/coast. Tl;dr version of problem is, that for given map of landscape, I should print out length of coastline (without inner islands).
My idea was, to solve this by adding additional layer and then start DFS, so the algorithm will walk through every possible tile in map, and then watch on every tile, how many borders are around the tile.
However, for specific input, is my algorithm not working. When I've submitted the solution on this site (open.kattis), it says, that my program is giving wrong answer in 9th of 26 tests (previous 8 test were ok), but without any further explanation.
Can somebody look at my program, and say me, why is it bad? Where did I do mistake? Thanks
#include <iostream>
#include <stack>
#include <sstream>
using namespace std;
int main() {
string line;
getline(cin, line);
int rows = 0;
int columns = 0;
stringstream stream(line);
stream >> rows;
stream >> columns;
int map[rows][columns];
for (int i = 0; i < rows; i++) {
getline(cin, line);
for (int j = 0; j < columns; j++) {
map[i][j] = line[j] - 48;
}
}
//parsed landscape into 2d array
// int rows = 5;
// int columns = 6;
// int map[rows][columns] = {
// {0, 1, 1, 1, 1, 0,},
// {0, 1, 0, 1, 1, 0,},
// {1, 1, 1, 0, 0, 0,},
// {0, 0, 0, 0, 1, 0,},
// {0, 0, 0, 0, 0, 0,},
// };
int bigMap[rows+2][columns+2];
bool visited[rows+2][columns+2];
//create bigger map, so DFS can start from corner and assume
//that there is water around everywhere
//also initialize array visited for DFS
//add 2 new rows, before and after existing one
for (int i = 0; i < columns+2; i++) {
bigMap[0][i] = 0;
bigMap[rows + 1][i] = 0;
visited[0][i] = false;
visited[rows + 1][i] = false;
}
//add 2 new columns, before and after existing
//copy original map to new one
for (int i = 0; i < rows; i++) {
bigMap[i+1][0] = 0;
bigMap[i+1][columns + 1] = 0;
visited[i+1][0] = false;
visited[i+1][columns + 1] = false;
for (int j = 0; j < columns; j++) {
bigMap[i+1][j+1] = map[i][j];
visited[i+1][j+1] = false;
}
}
rows += 2;
columns += 2;
//starting DFS
int x = 0, y = 0;
//visited[x][y] = true; <-- edit
pair <int, int> coordinates;
coordinates.first = x;
coordinates.second = y;
stack<pair <int, int> > st;
//first vertex in stack
st.push(coordinates);
//total sum of borders
int borders = 0;
while(!st.empty()) {
//check coordinates in each round
x = st.top().first;
y = st.top().second;
//navigate to new vertex (only if new vertex wasn't visited (visited[x][y] == 0) and only
//if there is water (bigMap[x][y] == 0) and check if new vertex is still in the map
//if there is no possible vertex, then we reached the end so then pop the vertex and
//look in another way
if (visited[x][y+1] == 0 && bigMap[x][y+1] == 0 && y + 1 < columns) {
y++;
coordinates.second = y;
st.push(coordinates);
} else {
if (visited[x+1][y] == 0 && bigMap[x+1][y] == 0 && x + 1 < rows) {
x++;
coordinates.first = x;
st.push(coordinates);
} else {
if (visited[x][y-1] == 0 && bigMap[x][y-1] == 0 && y > 0) {
y--;
coordinates.second = y;
st.push(coordinates);
} else {
if (visited[x-1][y] == 0 && bigMap[x-1][y] == 0 && x > 0) {
x--;
coordinates.first = x;
st.push(coordinates);
} else {
st.pop();
continue;
}
}
}
}
//visited new vertex, so look around him and count borders
visited[x][y] = true;
if (bigMap[x][y+1] == 1 && y + 1 < columns) borders++;
if (bigMap[x+1][y] == 1 && x + 1< rows) borders++;
if (bigMap[x][y-1] == 1 && y > 0) borders++;
if (bigMap[x-1][y] == 1 && x > 0) borders++;
}
cout << borders << endl;
return 0;
The issue is that you are reusing the variable coordinates each time around the loop without setting it to the correct value. Your if test cascade is assuming that coordinates is set to the current location. This is only true while you are descending in your dfs. Once you start ascending again, the coordinate will be pointing to the wrong place.
Simple solution, add
coordinates = st.top();
at the top of your loop.
Here is a sample map that it will currently get wrong.
5 6
000000
011100
001010
000100
000000
Answer should be 14, but currently you get 18 as the program reaches the lake at row 3, column 4.
To check that it is doing this, add a debugging line at the end of your loop, where it is adding the borders.
cout << "adding " << x << " " << y << "\n";
You can then verify if the program is considering any locations it shouldn't.
I think it will fail for {1,0,0,0},{0,1,1,0},{0,1,1,0},{0,0,0,0}. This is because the walk through is prevented from completing due to setting visited=true for vertex 0,0. Set it false for 0,0 instead should improve things. Hope it helps.