I've been struggling to understand how to work with pointers generally. I have in the example below a little sketch of an update function (updateGrid) for Game of life. The idea is to update the state of all cells in the grid between true and false (as you might know).
However, I'm supposed to use pointers in order to alternate between the 'previous' and 'new' state of the grid. But I don't seem to figure out how to implement this concept of alternating pointers without making a copy of the current cells grid. Any idea?
By the way, my code below works so far just fine.
// ---------- Global Variables ----------
bool cells[MAX_SIZE][MAX_SIZE];
bool cells_next[MAX_SIZE][MAX_SIZE];
bool (*ptr)[MAX_SIZE][MAX_SIZE];
bool (*ptr_next)[MAX_SIZE][MAX_SIZE];
ptr = &cells;
ptr_next = &cells_next;
// ---------- update state ----------
void updateState() {
for (int row = 0; row < MAX_SIZE; ++row) {
for (int col = 0; col < MAX_SIZE; ++col) {
if (((*ptr)[row][col]) == 1) {
if ((numAliveNeighbors(row, col) < 2)
|| (numAliveNeighbors(row, col) > 3)) {
(*ptr_next)[row][col] = 0;
} else {
(*ptr_next)[row][col] = 1;
}
} else if (((*ptr)[row][col]) == 0) {
if (numAliveNeighbors(row, col) == 3) {
(*ptr_next)[row][col] = 1;
} else {
(*ptr_next)[row][col] = 0;
}
}
}
}
for (int row = 0; row < MAX_SIZE; ++row) {
for (int col = 0; col < MAX_SIZE; ++col) {
(*ptr)[row][col] = (*ptr_next)[row][col];
(*ptr_next)[row][col] = 0;
}
}
PS: My problem explanation may seem a little bumpy so don't hesitate for further infos.
Many thanks in advance :)
Note these remarks:
You should use pointer to rows instead of pointers to 2D arrays.
You can alternate the pointers by swapping the via a temporary variable.
The code implements John Conway's famous Game of Life generations. ptr points to the current board and ptr_next points to the next generation. update() computes the new board applying the rules for cell death and birth. When the new board has been fully updated, the pointers are swapped, so ptr now points to the new board. This is faster than copying the full board from cells_next to cells.
Here is a modified version:
// ---------- Global Variables ----------
bool cells[MAX_SIZE][MAX_SIZE];
bool cells_next[MAX_SIZE][MAX_SIZE];
bool (*ptr)[MAX_SIZE] = cells;
bool (*ptr_next)[MAX_SIZE] = cells_next;
// ---------- update state ----------
void updateState() {
for (int row = 0; row < MAX_SIZE; ++row) {
for (int col = 0; col < MAX_SIZE; ++col) {
if (ptr[row][col]) {
if ((numAliveNeighbors(row, col) < 2)
|| (numAliveNeighbors(row, col) > 3)) {
ptr_next[row][col] = 0;
} else {
ptr_next[row][col] = 1;
}
} else {
if (numAliveNeighbors(row, col) == 3) {
ptr_next[row][col] = 1;
} else {
ptr_next[row][col] = 0;
}
}
}
}
// swap the pointers
bool (*tmp)[MAX_SIZE] = ptr;
ptr = ptr_next;
ptr_next = tmp;
}
Note that numAliveNeighbors should probably take ptr as an argument instead of implicitly via a global variable.
Related
I am writing a function to increase the values of all elements in an array until they all reach a specified value, this value can be different for each item. This is what I have so far.
Edit: I forgot to mention that the reason not to set it directly as in arr[i].value = arr[i].setpoint (as pointed out by kaylum) it is because there is a limitation where, while incrementing, the values in the array can only differ by the same unit of increment, in this case 1. So abs(arr[i].value - arr[i+1].value) <= 1. Once an element reaches the setpoint it is free of this limitation (so that the other elements can reach its setpoint)
#include <stdio.h>
typedef struct
{
unsigned value;
unsigned setpoint;
} ValSet;
void set_all(ValSet arr[static 1], size_t arr_size)
{
for (size_t cnt = arr_size; cnt;)
{
cnt = arr_size;
for (size_t i = 0; i < arr_size; i++)
{
if (arr[i].value != arr[i].setpoint)
{
arr[i].value++;
}
else
{
cnt--;
}
}
}
}
int main()
{
ValSet arr[2] = {{0, 2}, {0, 4}};
set_all(arr, 2);
return 0;
}
This generates the desired output so, after the call to set_all(arr, 2), arr[0].value = 2 and arr[1].value = 4, but I am not sure this is the best idea. Is there a better way to achieve this?
You were a bit unspecific about what you want exactly, so here are some solutions:
typedef struct {
unsigned value;
unsigned setpoint;
} ValSet;
/**
* for each element:
* increases value by one, until value is not smaller than setpoint
* will never decrease value
*/
void increase_all_slow(ValSet* arr, int len) {
for (int i = 0; i < len; i++) {
while (arr[i].value < arr[i].setpoint) {
arr[i].value++;
}
}
}
/**
* for each element:
* sets value to setpoint, if value is smaller than setpoint
* will never decrease value
*/
void increase_all(ValSet* arr, int len) {
for (int i = 0; i < len; i++) {
if (arr[i].value < arr[i].setpoint) {
arr[i].value = arr[i].setpoint;
}
}
}
/**
* for each element:
* sets value to setpoint
* decreases value if less than setpoint
*/
void set_all(ValSet* arr, int len) {
for (int i = 0; i < len; i++) {
arr[i].value = arr[i].setpoint;
}
}
Your implementation has a lot of redundant checks, every element will be compared if (arr.value[i] != arr.setpoint[i]) as long as any element is not set correctly. This will make it very slow.
I hope my code is self explanatory (I even added comments where usually you don't need them). If not, feel free to ask
Edit:
Now I know what you want. Next time tell us before:
typedef struct {
unsigned value;
unsigned setpoint;
} ValSet;
/**
* Until every element is equal (or bigger) to its corresponding setpoint.
* Every elements value that is not, will be increased.
*/
void increase_all(ValSet* arr, int len) {
int max_allowed = INT_MAX;
for (int i = 0; i < len; i++) {
if (arr[i].value < max_allowed) {
max_allowed = arr[i].value;
}
}
bool done = false;
while (!done) {
max_allowed++;
done = true;
for (int i = 0; i < len; i++) {
if (arr[i].value < arr[i].setpoint && arr[i].value < max_allowed) {
arr[i].value++;
done = false;
}
}
}
}
Hi im having problems with my c code it keeps crashing with no error and im not sure why. i am trying to find the value at a point inside a 2d array for example [1][1] and see what the value is there (only 1 or a 0) and then process the value depending on if its 1 or a 0 but the program keeps crashing with no error and im not sure why.please help
typedef struct gol{ // structure containing a square board
int **board; // pointer to a pointer
size_t size; //size_t = unnasigned value
}gol;
the struct is created in main using
struct gol *GAME;
GAME = create_gol(30);
using an if menu options if option is selected it will just call
next pattern function but it crashes
gol* create_gol(size_t size){
struct gol *Game_Of_Life;
Game_Of_Life = (struct gol*)malloc(sizeof(struct gol*)); //dynamically create the struct the ptr is pointing to **IMPORTANT
Gameboard = new int*[size];
for (int i = 0; i < size; ++i) {
Gameboard[i] = new int[size];
// each i-the pointer is now pointing to dynamic array (size 20) of actual int values
}
for (int i = 0; i < size; ++i) { // for each row
for (int j = 0; j < size; ++j) { // for each column
Gameboard[i][j] = 0;
}
}
Game_Of_Life->board=Gameboard;
Game_Of_Life->size=size;
return Game_Of_Life;
}
void next_pattern(gol* g)
{
for (int i = 0; i < 20; ++i) { // for each row
for (int j = 0; j < 20; ++j) { // for each column
int sum = neighbour_sum(g,i,j);
if (g->board[i][j]==1){
if (sum<2){
g->board[i][j]=0;
}
if (sum==3 || sum==2 ){
g->board[i][j]=1;
}
if (sum>3){
g->board[i][j]=0;
}
}
if (g->board[i][j]==0 && sum==3){
g->board[i][j]=1;
}
}
}
}
updates neighbour sum so it cant go out of bounds program still crashing
int neighbour_sum(gol* g, int i, int j)
{ int sum;
if ((g->board[(i-1+g->size)%g->size][j])==1){ // left
sum++;
}
if ((g->board[(i-1+g->size)%g->size][(j-1+g->size)%g->size])==1){//left up
sum++;
}
if ((g->board[i][(j-1+g->size)%g->size])==1){ //up
sum++;
}
if ((g->board[(i+1)%g->size][(j+1)%g->size])==1){ //right up
sum++;
}
if ((g->board[i][(j+1)%g->size])==1){ //right
sum++;
}
if ((g->board[(i+1)%g->size][(j+1)]%g->size)==1){//right bottom
sum++;
}
if ((g->board[i][(j+1)%g->size])==1){//bottom
sum++;
}
if ((g->board[(i-1+g->size)%g->size][(j+1)%g->size])==1){// bottom left
sum++;
}
return sum;
}
These lines
for (int i = 0; i < 20; ++i) { // for each row
for (int j = 0; j < 20; ++j) { // for each column
int sum = neighbour_sum(g,i,j);
means that you first call neighbour_sum with both i and j being zero.
Inside neighbour_sum you do:
if ((g->board[(i-1)][j])==1){ // left
^^^^
So since both i and j are zero, it is actually:
if ((g->board[-1][0])==1){ // left
^^^^
ups
So you access the array out of bounds. That may cause a crash. In any case it is illegal.
The general problem seems to be that you don't handle when the point is at the edge of the board.
edit after OP posted more code
This is wrong
Game_Of_Life = (struct gol*)malloc(sizeof(struct gol*));
^^^
do
Game_Of_Life = malloc(sizeof(struct gol));
I found the solution in the end there where a number of issues including i was looking for value outside of the array that was solved using
if ((g->board[(i-1+g->size)%g->size][j])==1){ // left
sum++;
}
i also was using c++ syntax instead of c syntax witch was resolved using the malloc function
Game_Of_Life = (struct gol*)malloc(sizeof(struct gol));
and the last issue causing the crashing still was the function neighbour sum was returning -2 because it wasn't initialized at 0 properly
int sum = 0;
I'm taking a computer science class at my high school, and we learned a lesson on selection sort today. I wrote a program (it's probably clumsy, but please bear with me, I'm learning) and it works in that it sorts, but sometimes it throws an ArrayIndexOutOfBoundsException. Only sometimes. I don't know how this is possible, because I deal with the same array throughout the entire program and arrays have a fixed length. If anyone has some insight it would be extremely helpful.
I think the error has something to do with int first = y[movedVariable];. However, I don't understand how movedVariable can be out of bounds, because I'm pretty sure I wrote my program so that it would be < the length of the array.
public class selectionSort
{
public static int[] array;
public static int movedVariable = 0;
public static void main()
{
array = new int[10];
int x;
for (int count = 0; count < array.length; count++)
{
if (count == 0)
{
x = (int)(Math.random()*100+2);
array[count] = x;
}
else
{
x = (int)(Math.random()*100+2);
for (int y = 0; y < count; y++)
{
while(x == array[y])
{
x = (int)(Math.random()*100+2);
}
}
array[count] = x;
}
}
sort(array);
}
public static void sort(int[] x)
{
int thing = 0;
for(int hello = 0; hello < x.length; hello++)
{
int part = x[thing];
for ( int count = thing; count < x.length-1; count++)
{
if( part > x[count+1] )
{
part = x[count+1];
}
}
thing++;
swap( x, part);
}
int f = 0;
String output = "";
for( int val : x )
{
if (f%10 == 0)
{output += "\n";}
output += val + " ";
f++;
}
System.out.print(output);
}
public static int[] swap(int [] y, int num)
{
int count = 0;
int index = 0;
for ( count = 0; count < y.length; count++)
{
if (y[count] == num)
{index = count;}
}
int first = y[movedVariable];
y[movedVariable] = y[index];
y[index] = first;
movedVariable++;
return y;
}
}
For fun, I ran your code for 1,000,000 iterations and no out of bounds exception, unless I did not clear the static movedVariable to 0 before each iteration.
Since movedVariable is static after the first 10 calls to swap() it will be 10 and if another call is made to swap you'll get the index out of bounds. However, this can only happen if you call sort() more than once per run. Only use static for values that need to be preserved between instances of your class. Non statics that are part of the your instance state. Local variables for everything else. Otherwise your are creating a mine field of bugs just waiting to happen.
I refactored your class to remove variables that have the same functionality. For example your thing and your movedVariable and your hello variable in sort() can be just one variable. Try to eliminate multiple variables that do the same thing, like the plague. It is a source of non obvious bugs.
Also, you are passing the value in the array to swap then looking for it in the array to get the index, this is a waste of time. Just pass in the index to swap. It also creates a problem for your sort function when you have the same value at two different places. Swap will use the last one it finds. sort() should handle duplicate values in the array. That explains why you initialized your array with unique values. You should not have to do that. Actually you should test your code with duplicates explicitly added to make sure your function works.
I moved printing of the array out of sort into its own method. It is useful for debugging at intermediate steps not just when the sort is done.
I tried to leave variable names the same and the logic unchanged so you can follow the changes.
public class Main
{
public static void sort(int[] x)
{
for (int movedVariable = 0; movedVariable < x.length; movedVariable++)
{
int part = x[movedVariable];
int index = movedVariable;
for (int count = movedVariable; count < x.length - 1; count++)
{
if (part > x[count + 1])
{
part = x[count + 1];
index = count + 1;
}
}
swap(x, index, movedVariable);
}
printArray(x);
}
private static void printArray(int[] x)
{
int f = 0;
String output = "";
for (int val : x)
{
if (f % 10 == 0)
{
output += "\n";
}
output += val + " ";
f++;
}
System.out.print(output);
}
public static int[] swap(int[] y, int index, int movedVariable)
{
int first = y[movedVariable];
y[movedVariable] = y[index];
y[index] = first;
return y;
}
public static void main(String[] args)
{
int[] array = new int[10];
int x = 0;
for (int count = 0; count < array.length; count++)
{
for (int y = count; --y >= 0; )
{
do
{
x = (int) (Math.random() * 100 + 2);
}
while (x == array[y]);
}
array[count] = x;
}
printArray(array);
sort(array);
}
}
I need to swap a 2d array of variable length but for some reason when the function to swap the elements is called it returns false. The swap code appears logical to me it does not work. Here is a snippet of the code.
bool swap(int tile)
{
for(j = 0; j < d; j++)
{
if (game[i][j]==tile && game[i][j + 1]==0)//swap tile left of zero
{
a = game[i][j +1];
b = game[i][j] ;
int temp = a;
a = b;
b = temp;
game[i][j] = a;
game[i][j+1] = b;
}
}
}
What is wrong here and how can I correct. The reason is just as important as the guidance to resolving. Thanks much!
You are doing a double swap, in effect making no swap at all.
It can be really simple since you already know the value of game[i][j+1] to be zero. All you have to do is
game[i][j+1] = game[i][j];
game[i][j] = 0;
You don't have any return
You should do like the following code
bool swap(int tile)
{
bool worked = false;
for(j = 0; j < d; j++)
{
if (game[i][j]==tile && game[i][j + 1]==0)//swap tile left of zero
{
int temp = game[i][j +1];
game[i][j+1] = game[i][j];
game[i][j] = temp;
worked = true;
}
}
return worked;
}
I need an idea how to effectively find areas below marked with 0 in two-dimensional array. It should be noted that there are other areas, such as this picture shows one of two who owns coordinate (0.0) and the other owns coordinate (21.3).
00000000000111110000111
00000000001111110000111
00000000011111100000111
00000000000111000001101
00000000011100000011101
00000001111100001111001
00000111111111011111001
00000001111100001111001
00000000010000000011001
00000000000000000001111
Of course a real array will be much larger.
Recursive version that goes to all sides and stops at mark 1 or array side isn't fast enough.
It looks like you're looking for a flood-fill algorithm. The wikipedia page I linked lists a few algorithms which may be faster than the obvious recursive method.
Flood-fill will be a good match if the areas you're looking for are small compared to the entire array, and you don't need to search for all of them. If you need to know about most or all of them, then computing them all in a single shot using a union-merge based connected component labeling algorithm may be a better choice. Here's some code that implements such an algorithm (note that I've altered it to run in a single pass):
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <map>
const char *data[] = {
"00000000000111110000111",
"00000000001111110000111",
"00000000011111100000111",
"00000000000111000001101",
"00000000011100000011101",
"00000001111100001111001",
"00000111111111111111001",
"00000001111100001111001",
"00000000010000000011001",
"00000000000000000001111",
NULL
};
struct label {
private:
int index;
int rank;
label *parent;
public:
label ()
: index(-1), rank(0), parent(this)
{ }
int getIndex(int &maxIndex) {
if (parent != this)
return find()->getIndex(maxIndex);
if (index < 0)
index = maxIndex++;
return index;
}
label *find() {
if (parent == this)
return this;
parent = parent->find();
return parent;
}
label *merge(label *other)
{
label *xRoot = find();
label *yRoot = other->find();
if (xRoot == yRoot)
return xRoot;
if (xRoot->rank > yRoot->rank) {
yRoot->parent = xRoot;
return xRoot;
} else {
xRoot->parent = yRoot;
if (xRoot->rank == yRoot->rank)
yRoot->rank++;
return yRoot;
}
}
};
int width, height;
int main() {
for (int i = 0; data[0][i]; i++)
width = i + 1;
for (int i = 0; data[i]; i++) {
height = i + 1;
}
std::vector<std::vector<unsigned short> > lblinfo;
lblinfo.resize(height, std::vector<unsigned short>(width, 0));
std::vector<label *> labels;
labels.push_back(NULL); // 0 is used as an unassigned flag
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (data[y][x] == '1')
continue;
// Try to find a neighboring label
unsigned short lblid = 0;
if (x != 0 && lblinfo[y][x-1] != 0)
lblid = lblinfo[y][x-1];
// merge with cells above
if (y != 0) {
for (int x2 = x - 1; x2 <= x + 1; x2++) {
if (x2 < 0)
continue;
if (x2 >= width)
continue;
unsigned short otherid = lblinfo[y - 1][x2];
if (!otherid)
continue;
if (!lblid)
lblid = otherid;
else {
labels[lblid]->merge(labels[otherid]);
}
}
}
if (!lblid) {
// assign a new label
lblid = labels.size();
labels.push_back(new label);
}
lblinfo[y][x] = lblid;
}
}
// Assign indices to the labels by set and print the resulting sets
int maxindex = 0;
static const char chars[] = "abcefghijklmnopqrstuvwxyz";
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
unsigned short labelid = lblinfo[y][x];
if (labelid == 0) {
putchar(data[y][x]);
continue;
}
label *label = labels[labelid];
int idx = label->getIndex(maxindex);
if (idx >= sizeof(chars) - 1) {
printf("\n\n Too many labels to print!\n");
exit(1);
}
putchar(chars[idx]);
}
printf("\n");
}
return 0;
}