Conditional assigning a value to int variable in loop (optimization) - optimization

Let's say that we have two dimensional array of bools which represent map of simple game. Every cell of array can be set to true if cell is occupied by some game's object (else false).
We want to update map in loop regarding to objects' behaviour. Let's say (because of some reasons) we are not able to update only some regions of the map, we have to iterate every cell in the array and negate it's value if object has changed its position.
We know that in every array's update there are only few changes but array is huge. And now comes the question.
What is more optimal.
(1) This:
for (int i = 0; i < Rows; i++)
for (int j = 0; j < Cols; j++)
{
bool newValue = update(i,j);
arr[i,j] = arr[i,j] != newValue ? newValue : arr[i,j];
}
(2) this:
for (int i = 0; i < Rows; i++)
for (int j = 0; j < Cols; j++)
{
bool newValue = update(i,j);
if(newValue != arr[i,j])
arr[i,j] = newValue;
}
(3) or maybe this:
for (int i = 0; i < Rows; i++)
for (int j = 0; j < Cols; j++)
{
arr[i,j] = update(i,j);
}
I think (1) is worst solution here. So (2) vs (3).

No 3. There is no reason to write the code like you did in #2. You can remove the if without any problems.

Related

Populating table causes unexpected results

I am totally stumped. I have been debugging this for hours. I am allocating a table of 100 UInt32s by 100. I am loading a table of values and writing them to the 2D array. For some bizarre reason when I get to row 67, column 0 the writes appear to wrap back around to row 0 element 0.
I have rewritten it to allocate a list of arrays rather than a single malloc. Same exact behavior. I have tried doing math for the index: _map[row * 100 + column] instead of _map[i,j] and that leads to other strange behavior. I was thinking maybe something is overflowing, but I can't see how since the data is so small. Obviously I am doing something stupid but I just... can't.. see it.
Code snippet:
_map = malloc(100 * 100 * sizeof(UInt32));
int i = 0;
for (i=0; i <_columns; i++)
{
columnList = [[lineList objectAtIndex:i] componentsSeparatedByString:#","];
int j = 0;
for (j=0; j < _rows; j++)
{
UInt32 dataInt = atoi([[columnList objectAtIndex:j] UTF8String]);
// Convert the data
NSDictionary* tDict = [fileMap objectForKey:[NSString stringWithFormat:#"%i", dataInt]];
int newVal = [[tDict objectForKey:#"convert"] integerValue];
_map[i,j] = (UInt32)newVal;
UInt32 y = _map[i,j];
// This trips at row 67 element 0
if (_map[0,0] != 1)
printf("Here\n");
}
}
Any help would be absolutely most awesomely appreciated.
As I mention below, this code gives the same problem in that it corrupts the first line. As if every row is the same row:
int** testMap = malloc(100 * 100 * sizeof(int));
int data = 0;
for (int i = 0; i<100; i++)
{
for (int j = 0; j < 100; j++)
{
testMap[i, j] = data;
data++;
printf("(%i, %i)", i,j);
}
printf ("\n");
}

exc_bad_access (code= 2 address =0x0)

I am new to this, trying to make an Minesweeper iphone app
i used a IBButton to Reset mine fields
which is a 2 by 2 matrix of a struct
- (IBAction) Reset {
for (int x = 0 ; x < 10 ; x ++) {
for (int y = 0 ; y < 10 ; y++ ) {
f[x][y]->isOpen = NO;
f[x][y]->display = 0; //Going to make a search function for finding Number of mines next to it
int random = arc4random()%10;
if (random < 2) {
f[x][y]->isMine = YES;
} else {
f[x][y]->isMine = NO;
}
}
}
so i get the the error at the very first line of my for loop
f[x][y]->....
what did i do wrong here?
/edit
This is how i declared my f
struct feild *f[10][10];
struct feild{
bool isOpen;
bool isMine;
int display;
}
You haven't allocated any space for f, so f[x][y] will just contain junk memory and then the ->isOpen = NO access will blow up.
you need to do something like
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
f[i][j] = malloc(sizeof(struct feild));
}
}
before your code.

Dividing an array into separate arrays of four elements plus the reminder

I'm trying to divide an array into individual arrays of four elements, where the last array will contain the reminder. For example, if that main array's length property will be ten, three subarrays will be created - two consisting of four elements, and one of two elements.
The code I have right now looks like the following:
NSMutableArray *mainMutableArray = [NSMutableArray arrayWithObjects:#"First", #"Second", #"Third", #"Fourth", #"Fifth", #"Sixth", #"Seventh", #"Eighth", nil];
NSMutableArray *mutableArrayOfSubarrays = [NSMutableArray array];
int length = mainMutableArray.count / 4;
int location = 0;
for (int i = 0; i < length; i++)
{
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
This of course works only when the reminder is equal to 0.
Any help would be greatly appreciated.
Ok, here we go:
int length = mainMutableArray.count;
for (int location = 0; location < length; location+=4)
{
unsigned int Size=length-location;
if (Size>4) Size=4;
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, Size)]];
}
If you use a while loop, you can make the condition describe what you are actually trying to do:
NSUInteger length = [mainMutableArray count];
NSUInteger location = 0;
// Until the location is less than four away from the end
while( location <= (length - 4) ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, 4)]];
location += 4;
}
// Pick up the remainder, if any
if( location != length ){
[mutableArrayOfSubarrays addObject:[mainMutableArray subarrayWithRange:NSMakeRange(location, length-location)]];
}
Loop from length*4 to mainMutableArray.count to get the remainder of the array.

when using NSUInteger in a decreasing for loop, how to determine >= 0

If I want to use a loop like
for (NSUInteger row = 10; row >= 0; row--) {
// do something
}
how do I get around the fact that row will always be > 0 since it's an unsigned integer. Does the middle construct of the for loop just become:
for (NSUInteger row = 10; row; row--) {
}
If you use NSInteger instead of NSUInteger this gets a bit simpler. Because NSInteger is a signed integer type, calling the decrement operator (--) on a variable with the value zero changes the value to -1, so you can test for this using a simple comparison:
for (NSInteger row = 10; row >= 0; row--) {
// do stuff with row
}
If you have to use an NSUInteger for some reason then calling the decrement operator on a variable with a value of zero will result in the variable's value wrapping around to the maximum possible value for NSUInteger. You can test for this using NSUIntegerMax.
for (NSUInteger row = 10; row != NSUIntegerMax; row--) {
// do stuff with row
}
Do you need an unsigned? If so, you'll have to come up with a test that does what you want. Possibly row>=0 && row<=10, although that's a bit clunky for my tastes.
Edit: Just wanted to add that the comparison of unsigned >=0 is superfluous, but if you are going to stick with unsigned, I would leave it, because it at least conveys intent.
You should either do this:
for (NSUInteger row = 10; row >= 1; row--) {
}
or this:
for (NSInteger row = 10; row >= 0; row--) {
}
for (NSUInteger index = 11; index > 0; index--) {
NSUInteger row = index-1;
}
If you really need to use a NSUInteger
for (NSUInteger row = 10; row >= 0; row--) {
// do something
if(row == 0) {break;}
}
Otherwise, try using a NSInteger as Simon Whitaker suggested
Another trick is to move decrement to condition check part. By the way this loop one operation less that classic one.
for (NSUInteger i = 10; i-- > 0;)
{
}

Array giving EXC_BAD_ACCESS in for loop

I have a C array defined in my method as:
int c = 4;
int r = 5;
keysArray[c][r];
I have this for loop, which works, populating the keysArray as expected.
for (int row = 0; row < r; row++) {
for (int column = 0; column < c; column++){
keysArray[column][row] = [anotherArray objectAtIndex:0];
NSLog(#"array1 %#",keysArray[column][row]);
[anotherArray removeObjectAtIndex:0];
}
}
Then in a for loop underneath, featuring exactly the same looping counter structure, when i try to NSLog the array, it gives an EXC_BAD_ACCESS.
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#",keysArray[column][row]); //EXC_BAD_ACCESS here
}
}
What would cause this to happen, given that the keysArray is defined in the method body, outside of both sets of loops?
Are the contents of anotherArray retained by some other object? If not, they do not exist anymore in the second loop. WTH are you using a C array to store Objective-C objects anyway?
int c = 4;
int r = 5;
NSMutableArray *keysArray = [[NSMutableArray alloc] initWithCapacity:c];
for (int column = 0; column < c; column++) {
[keysArray addObject:[NSMutableArray arrayWithCapacity:r]];
for (int row = 0; row < r; row++) {
[[keysArray objectAtIndex:column] addObject:[anotherArray objectAtIndex:0]];
[anotherArray removeObjectAtIndex:0];
}
}
for (int row = 0; row < r; row++){
for (int column = 0; column < c; column++) {
NSLog(#"array2: %#", [[keysArray objectAtIndex:column] objectAtIndex:row]);
}
}
You need to retain the objects held in your C array. Unlikes an NS*Array, a C array does not retain on adding to the array.
However, for a no-holes 2D array like that, I'd just use a single NSMutableArray. Any N-dimensional array can be represented as a line-- as a one dimensional array-- with simple math.
Namely, to determine the index of an object at (X,Y), use (Y * width) + X).
The only caveat is that NS*Array does not support "holes". You will need to fill the array row by row. That is, for a 3x4 (3 wide, 4 tall) array, you would fill it in the order 0,0, 1,0, 2,0, 0,1, 1,1, etc...
Obviously, insert and remove operations will mess up your 2D representation (but they would in an NSMutableArray of NSMutableArrays, too).
Alternatively, use NSPointerArray as it can have holes.
Could this be the problem :
[anotherArray removeObjectAtIndex:0];
try
keysArray[column][row] = [[anotherArray objectAtIndex:0] retain];
although if I were you I would use NSMutableArray of NSMutableArray instead