Game of life continues bounds - c++

So I've been trying my hand at game of life and I noticed that the cells only stay confined within the grid that I've created. I want to try and make it continuous so if a cell reaches one side it will continue from the other side. Similar to the game pac-man when you leave from the left to come back into the game from the right side. Here is an image of how it would look as the cell moves out of bounds http://i.stack.imgur.com/dofv6.png
Here is the code that I have which confines everything. So How would I make it wrap back around?
int NeighborhoodSum(int i, int j) {
int sum = 0;
int k, l;
for (k=i-1;k<=i+1;k++) {
for (l=j-1;l<=j+1;l++) {
if (k>=0 && k<gn && l>=0 && l<gm && !(k==i && l==j)) {
sum+=current[k][l];
}
}
}
return sum;
}
Based on dshepherd suggestion this is what I have come up with.
if (!(k == i && l == j)) {
sum += current[k][l];
} else if (k == 1 || k == -1) { // rows
sum += current[k+1][l];
} else if (l == 1 || l == -1) { // columns
sum += current[k][l+1];
}

Start considering a one dimension array, of size ARRAY_SIZE.
What do you want that array to return when you ask for a cell of a negative index ? What about a for an index >= ARRAY_SIZE ? What operators does that make you think of (hint : <= 0, % ARRAY_SIZE, ...)
This will lead you to a more generic solution that dshepherd's one, for example if you want in the future to be able to specify life / death rules more than just one index around the cell.

Assuming a grid size of 0 to n-1 for x and 0 to m-1 for y (where n is the size of the x dimension and m is the size of the y dimension, what you want to do is check if the coordinates are in-range, and move accordingly. So (pseudocode):
// normal move calculation code here
if (x < 0) { x = n-1; }
if (x >= n) { x = 0; }
if (y < 0) { y = m-1; }
if (y >= m) { y = 0; }
// carry out actual move here
With the start position marked as red, you need to calculate a movement into, or a breeding into, a new square: you need to check for whether it would fall out of bounds. If it does then the new cell would be born in either of the orange positions, if not it could be born
in any of the blue positions:
Hope that helps:) Let me know if you need more information though:)

It looks like you are taking a summation over nearest neighbours, so all you need to do to make it wrap around is to extend the summation to include the cells on the other side if (i,j) is an edge cell.
You could do this fairly easily by adding else statements to the central if to check for the cases where l or k are -1 or gn/gm (i.e. just past the edges) and add the appropriate term from the cell on the opposite side.
Update:
What you've added in your edit is not what I meant, and I'm pretty sure it won't work. I think you need to carefully think through exactly what it is that the initial code does before you go any further. Maybe get some paper and do some example cases by hand?
More specific advice (but do what I said above before you try to use this):
You can't directly take current[k][l] if k or l are negative or greater than gn/gm respectively because there is no array entry with that index (the program should segfault). What you actually want it to do is use the 0th entry anywhere that it would normally use the gnth entry, and so on for all the other boundaries.
You will probably need to split the if statement into 5 parts not 3 because the cases for k < 0 and k > gn are different (similarly for l).
You are comparing against completely the wrong values with (k == 1 || k == -1) and similarly for l

Related

Why does only backtracking work in this scenario?

I am solving this question on LeetCode.com:
In a gold mine grid of size m * n, each cell in this mine has an integer representing the amount of gold in that cell, 0 if it is empty. Return the maximum amount of gold you can collect under the conditions:- (a) Every time you are located in a cell you will collect all the gold in that cell; (b) From your position you can walk one step to the left, right, up or down. (c) You can't visit the same cell more than once; (d) Never visit a cell with 0 gold. (e) You can start and stop collecting gold from any position in the grid that has some gold.
For the grid: [[0,6,0],[5,8,7],[0,9,0]] the output is: 24.
I wrote the code below:
class Solution {
public:
int dig(vector<vector<int>>& grid, int i, int j) {
if(i>=grid.size() || i<0 || j>=grid[0].size() || j<0 || grid[i][j]==0) return 0;
//change begins...
int gold=0;
gold+=grid[i][j];
grid[i][j]=0;
gold+=max(dig(grid, i+1, j), max(dig(grid, i, j+1), max(dig(grid, i-1, j), dig(grid, i, j-1))));
return gold;
//change ends...
}
int getMaximumGold(vector<vector<int>>& grid) {
vector<vector<int>> gridCopy=grid;
int maxGold=0;
for(int i=0; i<grid.size(); i++) {
for(int j=0; j<grid[0].size(); j++) {
if(grid[i][j]!=0) {
maxGold=max(maxGold, dig(gridCopy, i, j));
gridCopy=grid;
}
}
}
return maxGold;
}
};
However, it breaks on the input [[1,0,7,0,0,0],[2,0,6,0,1,0],[3,5,6,7,4,2],[4,3,1,0,2,0],[3,0,5,0,20,0]]; yielding 58 instead of 60.
There's another code that I found here, which is identical, except in the commented part above, wherein they have the below lines instead:
g[i][j] = -g[i][j];
auto res = max({ dfs(g, i + 1, j), dfs(g, i, j + 1), dfs(g, i - 1, j), dfs(g, i, j - 1) });
g[i][j] = -g[i][j];
return g[i][j] + res;
(And of course, they don't assign grid to gridCopy in the nested for loop, since they revert the modified grid back to its original form).
I understand they are backtracking, while I am not. But I am unable to understand what I am doing incorrect, since logically, I am doing the exact same thing. I used debug statements to trace the issue, but it is becoming difficult to follow along since there are many recursive calls.
Could someone please point out what is the logical fallacy in my code above?
Thanks!
All your recursive calls might modify the grid, and don't restore it.
That means that the first visit to a cell will block it for all other subsequent attempts.
For instance, if dig(grid, i+1, j) is evaluated first, none of the cells that were visited during that computation are available when you do the other three directions.
If your code happens to start in the top left corner and go downwards first in your example, you will visit 1-2-3-4-3 and get stuck.
After that walk, there is no path from the top left corner any more, even though there were plenty of them from the beginning, and some of them pay a lot more than 13.
(You might think that you're going to find a path from either direction, but it depends on the evaluation order.)
Shared mutable state and recursion is a very tricky combination.
One thing which seems wrong in your code is:
//change begins...
int gold=0;
gold+=grid[i][j];
grid[i][j]=0;
gold+=max(dig(grid, i+1, j), max(dig(grid, i, j+1), max(dig(grid, i-1, j), dig(grid, i, j-1))));
return gold;
//change ends...
Here you have mutated the value of grid[i][j] and that changed value is impacting your input, i.e. your input set is wrong now. Since the value of the grid[i][j] is changed and thus this will impact the rest of the calculation.
What you can do is store the initial value of grid[i][j] somewhere in that recursion stack and reassign back to the grid[i][j] after you are done exploring all paths from that node.
eg: a slight modification in your logic
//change begins...
int gold=0;
gold+=grid[i][j];
int temp = grid[i][j];
grid[i][j]=0;
gold+=max(dig(grid, i+1, j), max(dig(grid, i, j+1), max(dig(grid, i-1, j), dig(grid, i, j-1))));
grid[i][j] = temp;
return gold;
//change ends...
You can also save creating a memory in your recursion stack if you use the solution there in your question.
Just to answer your concern why only backtracking can solve this problem:
You need to understand your solution, which seems like:
look at each grid item if that can be part of the solution set.
for that, you select one grid item (where item value should be greater than 0)
then you explore all surroundings from that item. And using DFS you keep on exploring their surroundings and their surroundings, etc, until the exit condition is met.
Now, in your solution, you have mutated the value of grid[i][j] (for understanding purpose, let us say grid[2][3] is mutated) which is fine if and only if that item selected is present in the final solution set.
But, while exploring other possibilities, if you may happen to find some possibility with a greater number of golds present. Then there also grid[2][3] will be involved. Which you have marked as 0, i.e. the calculation for that node will go wrong.
So, you need to restore the original value to the grid item grid[i][j]. The reason you are making that 0 is you don't want to include it again as you have already visited. But for other solution sets, you need the original value to be present there.

Chunks loading and sort

I working on clone of minecraft and i have 2 problem with chunk loading.
First: Determinate chunks to be loaded.
i found one way it's ugly but works fast for me
Define 3d array (array) (size : MAX_CHUNKS_X,MAX_CHUNKS_Y,MAX_CHUNKS_Z)
Fill 3d array with FALSE
While passing from list of chunks checking if chunk inside a vision range
if inside set array[chunk_x][chunk_y][chunk_z] = true;
After passing list begin bassing array
For all array[chunk_x][chunk_y][chunk_z] == false add to LoadingList chunk at chunk_x chunk_y chunk_z
Another ways to less ugly and still fast ?
Code:
ChunksRenderList.clear();
CChunk* Chunk = NULL;
s32 RootChunk_X_Location = (floor(RenderCenter.x) / CHUNK_SIZE);
s32 RootChunk_Y_Location = (floor(RenderCenter.y) / CHUNK_SIZE);
s32 RootChunk_Z_Location = (floor(RenderCenter.z) / CHUNK_SIZE);
if(RenderCenter.x < 0)
RootChunk_X_Location--;
if(RenderCenter.y < 0)
RootChunk_Y_Location--;
if(RenderCenter.z < 0)
RootChunk_Z_Location--;
core::vector3s RootChunkLocation(RootChunk_X_Location,RootChunk_Y_Location,RootChunk_Z_Location);
u32 XZ_ArraySide = (RenderDistance_XZ*2)+1;
u32 Y_ArraySide = (RenderDistance_Y*2)+1;
char array[XZ_ArraySide][Y_ArraySide][XZ_ArraySide];
memset(array,0,(XZ_ArraySide*XZ_ArraySide*Y_ArraySide));
for(auto it = Chunks.begin(); it != Chunks.end(); it++)
{
Chunk = (it->second);
if(Chunk->Locked)
continue;
if(Chunk->KeepAliveCounter <= 0)
{
ChunksUnloadList.push_back(Chunk);
continue;
}
else
{
Chunk->KeepAliveCounter -= WORLD_UPDATE_PERIOD;
Chunk->DistanceToCamera = RenderCenter.distance_to(Chunk->ChunkAbsolutePosition);
}
if(Chunk->ChunkPosition.x >= (RootChunk_X_Location - (s32)RenderDistance_XZ) && Chunk->ChunkPosition.x <= (RootChunk_X_Location + (s32)RenderDistance_XZ))
if(Chunk->ChunkPosition.y >= (RootChunk_Y_Location - (s32)RenderDistance_Y) && Chunk->ChunkPosition.y <= (RootChunk_Y_Location + (s32)RenderDistance_Y))
if(Chunk->ChunkPosition.z >= (RootChunk_Z_Location - (s32)RenderDistance_XZ) && Chunk->ChunkPosition.z <= (RootChunk_Z_Location + (s32)RenderDistance_XZ))
{
s32 PositionInMatrix_X = Chunk->ChunkPosition.x - (RootChunk_X_Location - (s32)RenderDistance_XZ);
s32 PositionInMatrix_Y = Chunk->ChunkPosition.y - (RootChunk_Y_Location - (s32)RenderDistance_Y);
s32 PositionInMatrix_Z = Chunk->ChunkPosition.z - (RootChunk_Z_Location - (s32)RenderDistance_XZ);
array[PositionInMatrix_X][PositionInMatrix_Y][PositionInMatrix_Z] = true;
Chunk->KeepAliveCounter = CHUNK_LIVE_TIME;
}
if(not Chunk->NeightboarsUpdated)
{
ChunksNeightboarUpdateList.push_back(Chunk);
}
if(not Chunk->ChunkUpdated)
{
ChunksRebuildList.push_back(Chunk);
}
if(not Chunk->Locked and Chunk->VisibleBlocks > 0)
{
ChunksRenderList.push_back(Chunk);
}
}
for(u32 y = 0; y < Y_ArraySide; y++)
for(u32 x = 0; x < XZ_ArraySide; x++)
for(u32 z = 0; z < XZ_ArraySide; z++)
{
s32 ChunkPosition_X = (s32)x + (RootChunk_X_Location - (s32)RenderDistance_XZ);
s32 ChunkPosition_Y = (s32)y + (RootChunk_Y_Location - (s32)RenderDistance_Y);
s32 ChunkPosition_Z = (s32)z + (RootChunk_Z_Location - (s32)RenderDistance_XZ);
if(array[x][y][z] == 0)
{
SPendingToLoad ToLoad;
ToLoad.Position.set(ChunkPosition_X,ChunkPosition_Y,ChunkPosition_Z);
ToLoad.DistanceToCamera = ToLoad.Position.distance_to_sqr(RootChunkLocation);
ChunksLoadList.push_back(ToLoad);
}
}
Second:
how to sort ChunksLoadList to take effect like left on this pic
https://www.dropbox.com/s/owjfaaekcj2m23w/58f2e4c8.png?dl=0
Red = nearest to ChunksLoadList.begin()
Blue = farest to ChunksLoadList.begin()
im try to use
ChunksLoadList.sort([&RootChunkLocation](SPendingToLoad& i,SPendingToLoad& j)
{
return i.DistanceToCamera < j.DistanceToCamera;
}
);
But it method to slow for big vision ranges...
How i must rewrite code to take fast wave-loading effect ?
Sorry me horrible english, i hope you understand me...
Lets first look at the distance sorting problem, if your ChunksLoadList is a std::list and not a std::vector or std::array(C++11) you have lost the performance race already! Bjarne Stroustrup: Why you should avoid Linked Lists Pay close attention to the graph!!!
If its still too slow after you've changed it into a std::vector you can try "this method I just invented(TM)"!
The best sorting algorithms are something like
O(C+K*N log log N) fastest?
With a horrible C constant prep time, horrible K per element and a very nice N log log N
For N -> infinity this gets to be O(N log log N)
BUT for this problem there is an even better algorithm!
Flood fill followed by an insertion sort, the flood fill produces a nearly sorted list in O(N) and the insertion sort secures the totally ordered list from the partially ordered in O(N) for a total of O(N) ...
O(C+K*N)
with a horrible constant prep time, and an awful per element but only N times
variant of wikipedia
Flood-fill (node, target-color, replacement-color):
If target-color is equal to replacement-color, return.
Set Q to the empty queue. [must be std::vector or std::array or this will fail]
Add camera node to the end of Q.
While Q is not empty:
Set n equal to the *first* element of Q.
Remove *first* element from Q.
If the color of n is equal to target-color:
Add n to the distance list as the next closed (this will be nearly correct)
Set the color of n to replacement-color and mark "n" as processed.
Add adjacent nodes to end of Q if they has not been processed yet. (x/y/z +1/-1)
Return.
Queue elements are x,y,z
use std::dequeue
The distance list must also be a random access contain, that is fully allocated from start of size (viewdistance*2+1)^3, that is potentially big.
If view distance 100 is 201^3 = ~80000000 voxels, did you really want this? if you need some info from it you must have some pointer or index, at least 4 bytes, this blows the cache away on most systems.
As a flood fill its not effective but as a approximation to distance it is.
You could stop here if your requirements are fulfilled.
IF you need total ordered then run an insertion-sort on the nearly sorted list O(N), but then you need to calculate the camera distance also.
Potential further optimization:
opaque voxels doesn't add neighbours that also are opaque.
air(totally transparent) doesn't add to the camera list but need to be there for the fill, in case a flying island is present.

How do I hide numbers from a table of sudoku?

I'm trying to write a program that will give the user a sudoku puzzle to solve. But I'm stuck on hiding numbers by difficulty level. How do I do that?
Considering you have a 9x9 matrix of integers
int sudoku[9][9];
and this matrix is filled with a correct Sudoku, just replace some entries by 0 for example. Remember that Sudoku are often symmetric around their centre.
// Hide (i,j) from solution
sudoku[i][j] = 0;
sudoku[8-i][8-j] = 0;
Each time you hide two numbers from the solution, check back with your solver that it can still be solved. Finally, associate difficulty with a certain amount of loops of such a process
for (k=0; k < difficulty; ) {
// randomly select (i,j) so that:
// - 0 <= i <= 4
// - 0 <= j <= 4
// - (i,j) != (4, 4)
// - solution[i][j] != 0 (i.e., (i, j) has not already been randomly selected
save1 = solution[i][j];
solution[i][j] = 0;
save2 = solution[8-i][8-j];
solution[8-i][8-j] = 0;
if (!can_be_solved(solution)) {
// (i, j) was not a good choice!
solution[i][j] = save1;
solution[8-i][8-j] = save2;
}
else {
// it's still OK, let's go one step further
k += 1;
}
}
//
}
You could write a sudoku solver and then just randomly generate sudoku boards and test if they are valid with your sudoku solver. In your method that generates the boards, you could have an input that specifies the number of numbers that will be shown on the beginning board. Take a look at the standard number of numbers for different difficulties and base it off of that.

Finding how many turns are in a grid of AxB

So, basically, check the picture below:
This is a grid of 4x5 explained, however the actual challenge requires you to input the grid dimensions. So, my job is to write a program that calculates the amount of turns you make (red dots in this case). The starting position is always in the bottom left corner. The guy is moving by the arrows of the clock ("right").
The program input / output is:
you input the grid dimensions:
4 5 (for example)
you output the amount of changes of direction.
7
So, I have absolutely no idea how it's done. The solution I have seen only is the following:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
long long n, i,pom,m;
int k,br=0;
cin>>n>>m;
if(n>m) {
int pom=n;
n=m;
m=n;
}
if(n+1>=m)
cout<<(n-1)+(m-1);
else
cout<<(n-1) +(n-1)+1;
return 0;
}
But I don't understand the following example... could anyone explain what's going? Or any other way of solving this problem is always welcome.
int res = 0;
if(height == width)
res = height * 2 - 2;//when height is odd than you will have 2 rows with single red dot
//when height is even you will have one row without red dot (all the rest have 2 red dots.
else if (width > height)
res = height * 2 - 1;//one rows with 1 red dot the rest with 2 red dots.
else //height > width
res = width * 2 - 2// 2 columns with one red dot and the rest with 2 red dots.
I am not a C++ guy so can't help in understanding the code. But can surely help understanding the situation here.
The situation is that the number of turns will depend only on one of the two dimensions. Which ever is less. So the number of turns depends on the smaller dimension and number of boxes on that side. Because here in picture when you take a 4X5 array, no matter how many you increase the width to. as long as the height is 4, the number of turns will remain 7 only.
But if you decrease the width from 4 to 3, number of turns depends on width now.
Now about the number of dots. If both dimensions are same and odd, then assume dimension to be 2A+1, then the number of turns will be 4*A.
If one dimension is smaller, then if the dimensions are same and even, then assume dimension to be 2*A ,then the number of turns will be 4A-2.
If the smaller dimension is even, then assume the dimension to be 2*A, then the number of turns will be 4A-1.
If the smaller dimension is odd, then assume the dimension to be 2A+1, then the number of turns will be 4A+1.
See if this works with your own new code.
This code conditionally swaps n and m to make n <= m:
if(n>m) {
int pom=n;
n=m;
m=n;
}
Given that, the condition n+1>=m is equivalent to n == m || n + 1 == m.
Note that both formulas (n-1)+(m-1) and (n-1) +(n-1)+1 give the same result for n + 1 == m.
So it is not really necessary to check whether n + 1 == m; it's only the special case n == m that matters. If n == m, then you can use the formula (n-1)+(m-1), or just 2 * n - 2. Otherwise, use the formula (n-1) +(n-1)+1, or just 2 * n - 1.
To rewrite the code:
int calculate_number_of_turns(int m, int n)
{
if (m == n)
return 2 * n - 2;
else
return 2 * std::min(m, n) - 1;
}
Edit:
If you want to write your code from scratch, without knowing the math in advance, you can write a recursive function at first.
If n = 2, it's easy to see that the answer is 3 (3 turns). If m = 2, then the answer is 2. Otherwise (assuming n > 2 and m > 2), the calculation involves invoking the same function for different arguments.
int calculate_number_of_turns(int m, int n)
{
if (n == 2)
return 3;
else if (m == 2)
return 2;
else
return calculate_number_of_turns(???, ???);
}
Imagine starting the path in your picture, and stopping right after you do the second turn. If you turn the picture upside-down, it's as if you reduced with and height by 1. So calling the same function for m - 1, n - 1 will calculate the number of turns left to do, in addition to the first 2 turns.
int calculate_number_of_turns(int m, int n)
{
if (n == 2)
return 3;
else if (m == 2)
return 2;
else
return 2 + calculate_number_of_turns(m - 1, n - 1);
}
Now, converting this recursive function to any simpler form is not too complicated (just calculate the number of times the function is going to call itself, until a termination condition holds).

How Can I Make My Array Rotation More Efficient?

How can I make my circular array rotation more efficient? I read in this thread about an excellent sorting algorithm, but it won't work for what I need because there are spaces at the end of the array that get sorted into the middle.
The rotation function needs to work for both left and right rotation. Not every space of the array will be filled.
void Quack::rotate(int r)
{
if(r > 0) //if r is positive, rotate left
{
for(int i = 0; i < r; i++)
items[(qBack + i) % qCapacity] = items[(qFront + i) % qCapacity];
//move items in array
}
else if(r < 0) //if r is negative, rotate right
{
for(int i = 0; i < (r * -1); i++)
items[(qFront - i - 1) % qCapacity] =
items[(qBack - i - 1) % qCapacity];
//move items in array
}
//if r = 0, nothing happens
//rotate front and back by r
qFront = (qFront + r) % qCapacity;
qBack = (qBack + r) % qCapacity;
}
I haven't used it, so I can't promise it will do everything you need. But you might want to look into simply replacing this function body with the std::rotate function.
It should already be well optimized, and will be much less likely to introduce bugs into your application.
http://www.sgi.com/tech/stl/rotate.html
If you want suggestions for optimization though, I recommend avoiding all modulo operations. They may require a divide, which is one of the most expensive operations you can perform on your processor. They are a convenient way to think about how to accomplish your goal, but could be very costly for your CPU to execute.
You can remove your modulo operators if you use two loops: one from the middle to the end, and the other from the beginning to the middle.
But if you can, see if you can avoid doing the rotation altogether. If you are careful you might be able to eliminate pointless full-array traversal/copy operations. See my comment on the OP for how to accomplish this.