C++ Run time efficiency - c++

I'm creating a hex board out of nodes.Everything I have in this bit of code works perfectly. My problem is the item that is starred slows down this loop from taking ~1 second to about 1 minute. It isn't the number of items in the vector because if i remove them all except the last one it still takes ~1 minute. either way there are no run time errors.
for (x = 0; x < size; ++x)
{
for (y = 0; y < size; ++y)
{
this->nodes[x][y].neighbors = std::vector<node>(6);
if ((x == 0) && (y == 0))
{
this->nodes[x][y].neighbors =
{
nodes[x + 1][y],
this->nodes[x][y + 1]
};
}
else if ((x == 0) && (y == max))
{
this->nodes[x][y].neighbors =
{
this->nodes[x + 1][y],
this->nodes[x][y - 1],
this->nodes[x + 1][y - 1]
};
}
else if ((x == max) && (y == 0))
{
this->nodes[x][y].neighbors =
{
this->nodes[x - 1][y],
this->nodes[x][y + 1],
this->nodes[x - 1][y + 1]
};
}
else if ((x == max) && (y == max))
{
this->nodes[x][y].neighbors =
{
this->nodes[x - 1][y],
this->nodes[x][y - 1]
};
}
else if (y == 0 && (x != 0 && x != max))
{
this->nodes[x][y].neighbors =
{
this->nodes[x - 1][y],
this->nodes[x + 1][y],
this->nodes[x - 1][y + 1],
this->nodes[x][y + 1]
};
}
else if (y == max && (x != 0 && x != max))
{
this->nodes[x][y].neighbors =
{
this->nodes[x - 1][y],
this->nodes[x + 1][y],
this->nodes[x - 1][y - 1],
this->nodes[x][y - 1]
};
}
else if (x == 0 && (y != 0 && y != max))
{
this->nodes[x][y].neighbors =
{
this->nodes[x][y - 1],
this->nodes[x][y + 1],
this->nodes[x + 1][y],
this->nodes[x + 1][y - 1]
};
}
else if (x == max && (y != 0 && y != max))
{
this->nodes[x][y].neighbors =
{
this->nodes[x][y - 1],
this->nodes[x][y + 1],
this->nodes[x - 1][y - 1],
this->nodes[x - 1][y]
};
}
else
{
this->nodes[x][y].neighbors =
{
this->nodes[x + 1][y],
this->nodes[x - 1][y],
this->nodes[x][y - 1],
this->nodes[x + 1][y - 1],
this->nodes[x][y + 1],
this->nodes[x - 1][y + 1]
};
}
}
}

Given the idea is to track neighbours that you know have been pre-created, you probably only want to keep a reference or pointer to them; you should not copy the nodes by value as you currently do.
You could use vector<reference_wrapper<node>> or vector<node*>, with respective initialisation like this:
nodes[x][y].neighbors = { ref(nodes[a][b]), ref(nodes[c][d])... };
nodes[x][y].neighbors = { &nodes[a][b], &nodes[c][d], ... };
With pointers, when you access neighbors[n] you'll obviously need to dereference the pointer too.
Regarding why it was so slow... the copying by value meant copying nodes into neighbours was copying all those neighbouring node's neighbours, and their neighbours, ad nauseum... getting slower and slower as the number of nodes with long neighbour hierarchies increased.

The slowness comes from 2 things:
The last else clause gets hit the most.
The last clause copies more node items than the rest
A few suggestions:
Use pointers or indexes not node objects for neighbors. Less copying.
It will be faster to have a fixed size array for neighbors. Will improve locality and memory significantly. You'll have to add a neighbor count for that array.

Related

Array wraparound going to null

I have a 2d char array, of which I am trying to retrieve the value of an opposite side while on the edge. Instead of retrieving that value, it keeps returning with null. Can't make heads or tails of what the problem is. Here is the code I traced the problem to.
int xO = x; int yO = y;
//reassigns to opposite side of array
if ((x == 0) && (xM == - 1)) { xM = mapSize - 1; }
if ((x == mapSize - 1) && (xM == 1)) { xM = 0 - (mapSize - 1); }
if ((y == 0) && (yM == - 1)) { yM = mapSize - 1; }
if ((y == mapSize - 1) && (yM == 1)) { yM = 0 - (mapSize - 1);
}
//Checks 9 chars around and assigns any found characters
if (mapPlates[x + xM][y + yM] == 0) {
std::cout << "//" + std::to_string(x + xM) + ", " + std::to_string(yM + y) + "; " + std::to_string(mapPlates[x + xM][y + yM]) + "//";
}
if (mapPlates[x + xM][y + yM] =! "%") {
remaining--;
mapPlates[xO][yO] = mapPlates[x + xM][y + yM];
std::cout << "{assigned " + std::to_string(mapPlates[xO][yO]) + " }";
}
return remaining;
}
Snippet of output(only returns values == null)(should be returning '%'):
```//14, 49; 0////14, 0; 0////14, 1; 0////19, 49; 0////20, 49; 0////19, 0;

Unable to resolve memory read and segmentation fault error in C++

I am coding a solution program for leetcode. I have encountered memory read errors and segmentation fault errors which I am unable to resolve. I have tried tinkering with the code to try and remove the errors.
For example: in the numIslands function's last lines, I had tried declaring coordinates as an array rather than a pointer but the results did not change.
*(last + 1) = *(coordinates + 1); does not seem to work at all in the numIslands function. I am totally blank about what to do next.
#include <iostream>
#include <string>
#include <vector>
#include <map>
namespace p200 {
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::vector;
using std::map;
}
class Solution {
private:
int count_islands = 0;
public:
int *last;
int numIslands(vector<vector<char>>& grid) {
if (grid.size() == 0) return count_islands;
if (grid.size() == 1 && grid[0].size() == 1) return grid[0][0] - 48;
vector<vector<int>> grid_copy;
vector<int> in;
for (size_t index = 0; index < grid.size(); ++index) {
for (size_t index0 = 0; index0 < grid[index].size(); ++index0) {
(grid[index][index0] == '0')
? in.push_back(0)
: in.push_back(INT_MAX);
}
grid_copy.push_back(in);
in.clear();
}
int * coordinates = new int[2];
*coordinates = 0;
*(coordinates + 1) = 0;
last = new int[2];
*last = *coordinates;
*(last + 1) = *(coordinates + 1);
find_island(grid_copy, coordinates);
return count_islands;
}
void find_island(vector<vector<int>> & arg_grid, int* arg_coordinates) {
if (arg_grid[*arg_coordinates][*(arg_coordinates + 1)] == INT_MAX) {
*last = *arg_coordinates;
*(last + 1) = *(arg_coordinates + 1);
map_island(arg_grid, arg_coordinates, 1);
} else {
if (*(arg_coordinates + 1) < arg_grid[*arg_coordinates].size()) {
*(arg_coordinates + 1) = *(arg_coordinates + 1) + 1;
find_island(arg_grid, arg_coordinates);
}
if (*(arg_coordinates + 1) == arg_grid[*arg_coordinates].size()) {
if (*arg_coordinates == arg_grid.size()) return;
*arg_coordinates = *arg_coordinates + 1;
*(arg_coordinates + 1) = 0;
find_island(arg_grid, arg_coordinates);
}
}
}
void map_island(vector<vector<int>> & arg_grid, int* arg_coordinates, int arg_new) {
arg_grid[*arg_coordinates][*(arg_coordinates + 1)] = count_islands + (arg_new * 1);
if (arg_new) count_islands = count_islands + 1;
if (*arg_coordinates != 0 && *arg_coordinates - 1 == INT_MAX) {
*arg_coordinates = *arg_coordinates - 1;
map_island(arg_grid, arg_coordinates, 0);
*arg_coordinates = *arg_coordinates + 1;
}
if ((*arg_coordinates < arg_grid.size() - 1)
&& *arg_coordinates + 1 == INT_MAX) {
*arg_coordinates = *arg_coordinates + 1;
map_island(arg_grid, arg_coordinates, 0);
*arg_coordinates = *arg_coordinates - 1;
}
if (*(arg_coordinates + 1) != 0 && *(arg_coordinates + 1) - 1 == INT_MAX) {
*(arg_coordinates + 1) = *(arg_coordinates + 1) - 1;
map_island(arg_grid, arg_coordinates, 0);
*(arg_coordinates + 1) = *(arg_coordinates + 1) + 1;
}
if (*(arg_coordinates + 1) < arg_grid[*arg_coordinates].size() - 1
&& *(arg_coordinates + 1) + 1 == INT_MAX) {
*(arg_coordinates + 1) = *(arg_coordinates + 1) + 1;
map_island(arg_grid, arg_coordinates, 0);
*(arg_coordinates + 1) = *(arg_coordinates + 1) - 1;
}
find_island(arg_grid, last);
}
};
int main() {
vector<vector<char>> input;
input.push_back(vector<char>({'1','1','1','1','0'}));
input.push_back(vector<char>({'1','1','0','1','0'}));
input.push_back(vector<char>({'1','1','0','0','0'}));
input.push_back(vector<char>({'0','0','0','0','0'}));
Solution solver;
cout << "Number of Island: " << solver.numIslands(input) << endl;
return 0;
}
I have ran it through gdb. After a bit of digging, the error is this:
void find_island(vector<vector<int>> & arg_grid, int* arg_coordinates) {
if (arg_grid[*arg_coordinates][*(arg_coordinates + 1)] == INT_MAX) {
*last = *arg_coordinates;
*(last + 1) = *(arg_coordinates + 1);
map_island(arg_grid, arg_coordinates, 1);
} else {
if (*(arg_coordinates + 1) < arg_grid[*arg_coordinates].size()) {
*(arg_coordinates + 1) = *(arg_coordinates + 1) + 1;
find_island(arg_grid, arg_coordinates);
}
if (*(arg_coordinates + 1) == arg_grid[*arg_coordinates].size()) {
if (*arg_coordinates == arg_grid.size()) return;
*arg_coordinates = *arg_coordinates + 1;
*(arg_coordinates + 1) = 0;
find_island(arg_grid, arg_coordinates);
}
}
}
In the second if, you do a bounds check and then increment. You should first increment then to the bounds check, like this:
*arg_coordinates = *arg_coordinates + 1;
if (*arg_coordinates == arg_grid.size()) return;
Also please usevector.at() instead of operator[]. It produces more readable and easier to interpret debug messages. Also as other people pointed it out *(arg_coordinates + 1) = arg_coordinates[1], which would make for a more readable code.
For other similar issues I recommend a debugger.
Edit: I ran the code and realised that there is some other bug within it. One of the islands is counted twice, so it gives the wrong result, but that is not technically the issue at hand.

When passing an data member array into a recursive procedure, is a new copy of that array created in each stack frame?

I am facing the issue that copy of an 2 dimensional array is not made in each stack frame of recursive call. I am doing indirect recursion.
I also tried sending my data in function call from main() function but the copy was not made. Same address was used in every recursive call.
class board
{
public:
int board_arr[8][8];
public:
board()
{
}
void player1Turn()
{
for (int i = 0; i < rowCount; i++)
{
for(int j = 0; j < rowCount; j ++ )
{
if (board_arr[i][j] == 1)
{
//checking if the pawn can move anywhere
if (i + 1 <=7 && j - 1 >= 0 && board_arr[i + 1][j - 1] == 0 )
{
board_arr[i][j] = 0;
board_arr[i + 1][j - 1] = 1;
player2Turn();
}
if (i + 1 <=7 && j + 1 <= 7 && board_arr[i + 1][j + 1] == 0)
{
board_arr[i][j] = 0;
board_arr[i + 1][j + 1] = 1;
player2Turn();
}
//opponent infront
//killing
//if opponent is infront and checking if you can kill it or not
if (i + 2 <= 7
&& i + 1 <= 7
&& j - 2 >=0
&& j - 1 >= 0
&& board_arr[i + 1][j - 1] == 2
&& (board_arr[i + 2][j - 2]==0))
{
board_arr[i][j] = 0;
board_arr[i + 2][j - 2] = 1;
board_arr[i + 1][j - 1] = 0;
cout << endl << "kill by p1 " << endl;
player2Turn();
}
if (i + 2 <= 7
&& i + 1 <= 7
&& j + 2 <= 7
&& j + 1 <=7
&& board_arr[i + 1][j + 1] == 2
&& (board_arr[i + 2][j + 2]==0))
{
board_arr[i][j] = 0;
board_arr[i + 1][j + 1] = 0;
board_arr[i + 2][j + 2] = 1;
cout << endl << "kill by p1 " << endl;
player2Turn();
}
}
}
}
}
void player2Turn()
{
for (int i = rowCount-1; i >= 0; i--)
{
for (int j = rowCount-1; j >= 0; j--)
{
if (board_arr[i][j] == 2)
{
//checking if the pawn can move anywhere
if (i - 1 >= 0 && j - 1 >= 0 && board_arr[i - 1][j - 1] == 0)
{
board_arr[i][j] = 0;
board_arr[i - 1][j - 1] = 2;
player1Turn();
}
if (i - 1 >= 0 && j + 1 <=7 && board_arr[i - 1][j + 1] == 0)
{
board_arr[i][j] = 0;
board_arr[i - 1][j + 1] = 2;
player1Turn();
}
//opponent infront
//killing
//if opponent is infront and checking if you can kill it or not
if (i - 2 >= 0
&& i - 1 >= 0
&& j - 2 >= 0
&& j - 1 >= 0
&& board_arr[i - 1][j - 1] == 1
&& (board_arr[i - 2][j - 2] ==0))
{
board_arr[i][j] = 0;
board_arr[i - 2][j - 2] = 2;
board_arr[i - 1][j - 1] = 0;
cout << endl << "kill by p2 " << endl;
player1Turn();
}
if (i + 2 <= 7
&& i - 1 >= 0
&& j + 2 <=7
&& j + 1 <= 7
&& board_arr[i - 1][j + 1] == 1
&& (board_arr[i - 2][j + 2] ==0))
{
board_arr[i][j] = 0;
board_arr[i - 2][j + 2] = 1;
board_arr[i - 1][j + 1] = 0;
cout << endl << "kill by p1 " << endl;
player1Turn();
}
}
}
}
}
};
same copy of the board_arr was used in each call.
You are not passing board_arr to a recursive method, that is those methods do not have that array in their parameters. So board_arr is not being copied.
Because those methods are instance methods of board class, everything is passed in each method call is this pointer to the instance of board.
You don't pass the array from function to function, but even if you did, arrays are (simplification) pointers, so even passing them manually from function to function will not create copies.
Use std::vector<> or std::array<>.

How can I fix the "Invalid memory reference" error in my code?

I'm working on a maze-solver robot for my arduino project. I want my robot to memorize the maze and then find the shortest path. I keep having a problem when the char array's lenght is 3.
The problem appears when the lenght is <= 3, so I tried diffrent stuff to make a particular case out of that, that's why the if (strlen(a) > 3) is there.
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int main()
{
char a[] = "LLLBLLLRBLLBSRSRS";
char b[200];
while(strcmp(a, b) != 0) {
strcpy(b, a); //sa verific daca se schimba sirul, daca nu inseamna ca a ajuns la minim
for(int i = 0; i < strlen(a) - 2; i++)
{
if(a[i] == 'L' && a[i + 1] == 'B' && a[i + 2] == 'R') //if urile astea cauta combinatii de cate 3 miscari sa optimizezi drumul
{
a[i] = 'B';
if (strlen(a) > 3) strcpy(a + i + 1, a + i + 3);
else a[i + 1] = '\0';
}
else if(a[i] == 'L' && a[i + 1] == 'B' && a[i + 2] == 'S')
{
a[i] = 'R';
if (strlen(a) > 3) strcpy(a + i + 1, a + i + 3);
else a[i + 1] = '\0';
}
else if(a[i] == 'L' && a[i + 1] == 'B' && a[i + 2] == 'L')
{
a[i] = 'S';
if (strlen(a) > 3) strcpy(a + i + 1, a + i + 3);
else a[i + 1] = '\0';
}
else if(a[i] == 'S' && a[i + 1] == 'B' && a[i + 2] == 'L')
{
a[i] = 'R';
if (strlen(a) > 3) strcpy(a + i + 1, a + i + 3);
else a[i + 1] = '\0';
}
else if(a[i] == 'S' && a[i + 1] == 'B' && a[i + 2] == 'S')
{
a[i] = 'B';
if (strlen(a) > 3) strcpy(a + i + 1, a + i + 3);
else a[i + 1] = '\0';
}
else if(a[i] == 'R' && a[i + 1] == 'B' && a[i + 2] == 'L')
{
a[i] = 'B';
if (strlen(a) > 3) strcpy(a + i + 1, a + i + 3);
else a[i + 1] = '\0';
}
}
cout << a << endl;
}
return 0;
}
This is the output:
LLSLLBRRSRS
LLSLBRSRS
LLSBSRS
LLBRS
LBS
and then the error message Runtime error(Exit status:139(Invalid memory reference)).
The goal is to make the last output be R, because LBS means R.
Thanks for the attention!
The reason for invalid memory reference is in the loop consition:
for(int i = 0; i < strlen(a) - 2; i++)
you are accessing a[i + 2] inside loop so the last iteration must end at i < strlen(a) - 3:
for(int i = 0; i < strlen(a) - 3; i++)
this just fixes your memory problem. you still get LBS as the last output.

Random unique number arrays comparison C++

I have two 2D arrays of type integer. I assign random values into both theses arrays. The values in the first column represent the x value for a and b, and the values in the second column represent the y value for a and b.
Declaring the arrays
int ROW(12), COLUMN(2);
int a[ROW][COLUMN];
int b[ROW][COLUMN];
Assigning random values to the arrays
for (int i(0); i < ROW; i++)
{
a[i][0] = Random(SIZEX - 2); //horizontal coordinate in range [1..(SIZEX - 2)]
a[i][1] = Random(SIZEY - 2); //vertical coordinate in range [1..(SIZEY - 2)]
}
for (int i(0); i < (ROW - 4); i++)
{
b[i][0] = Random(SIZEX - 2); //horizontal coordinate in range [1..(SIZEX - 2)]
b[i][1] = Random(SIZEY - 2); //vertical coordinate in range [1..(SIZEY - 2)]
}
I need to find a way in which I can compare the x and y value of an row, with the x and y value of each other row in each array aswell as with the other array and make sure each combination of x and y is unique for both of the arrays.
As the coordinates will relate to the position in another array.
I have a very messy solution which will work for one of the arrays.
for (int i(0); i < COLUMN; ++i)
{
if (i == 0)
{
while (b[i][0] == spot.x)
b[i][0] = Random(SIZEX - 2);
}
if (i == 1)
{
while ((b[i][0] == spot.x) || (b[i][0] == b[i - 1][0]))
b[i][0] = Random(SIZEX - 2);
}
if (i == 2)
{
while ((b[i][0] == spot.x) || (b[i][0] == b[i - 2][0]) || (b[i][0] == b[i - 1][0]))
b[i][0] = Random(SIZEX - 2);
}
if (i == 3)
{
while ((b[i][0] == spot.x) || (b[i][0] == b[i - 3][0]) || (b[i][0] == b[i - 2][0]) || (b[i][0] == b[i - 1][0]))
b[i][0] = Random(SIZEX - 2);
}
if (i == 4)
{
while ((b[i][0] == spot.x) || (b[i][0] == b[i - 4][0]) || (b[i][0] == b[i - 3][0]) || (b[i][0] == b[i - 2][0])
|| (b[i][0] == b[i - 1][0]))
b[i][0] = Random(SIZEX - 2);
}
if (i == 5)
{
while ((b[i][0] == spot.x) || (b[i][0] == b[i - 5][0]) || (b[i][0] == b[i - 4][0]) || (b[i][0] == b[i - 3][0])
|| (b[i][0] == b[i - 2][0]) || (b[i][0] == b[i - 1][0]))
b[i][0] = Random(SIZEX - 2);
}
if (i == 6)
{
while ((b[i][0] == spot.x) || (b[i][0] == b[i - 6][0]) || (b[i][0] == b[i - 5][0]) || (b[i][0] == b[i - 4][0])
|| (b[i][0] == b[i - 3][0]) || (b[i][0] == b[i - 2][0]) || (b[i][0] == b[i - 1][0]))
b[i][0] = Random(SIZEX - 2);
}
if (i == 7)
{
while ((b[i][0] == spot.x) || (b[i][0] == b[i - 7][0]) || (b[i][0] == b[i - 6][0]) || (b[i][0] == b[i - 5][0])
|| (b[i][0] == b[i - 4][0]) || (b[i][0] == b[i - 3][0]) || (b[i][0] == b[i - 2][0])
|| (b[i][0] == b[i - 1][0]))
b[i][0] = Random(SIZEX - 2);
}
}
But it only compares the x (first column). spot represents a struct variable.
May be you can try
for (int i=0;i<12;i++)
{for (int k=i+1;k<12;k++)
{if (a[i][0]==a[k][0])
cout<<"a["<<i<<"][0] same as a["<<k<<"][0]"<<endl;//you can assign a new number to a[k][0]
}};