Nested for loop not iterating properly - c#

Guys i have a really weird problem. I am trying to implement a nested for loop which splits up a rectangle into smaller blocks and then checks to see which of these smaller blocks have points from an array i have defined in them(big rectangle is 320*240 btw):
int[,] edgetrunc = new int[edgeIndex, 2]; //edgeIndex is the number of points in the external array
Array.Copy(edgePoint, edgetrunc, edgeIndex*2);//truncates the nulls from the tail of my array
int delx = 16;//width of block
int dely = 12;//height of block
int blockIndex = new int();
bool[] block = new bool[(depthFrame.Width/delx)*(depthFrame.Height/dely)];
for (int ymin = 0;ymin < depthFrame.Height;ymin += dely)
{
for (int xmin = 0; xmin < depthFrame.Width; xmin += delx)
{
blockIndex = (xmin / delx) + (ymin / dely);
for (int i = 0; i < edgeIndex; i++)
{
if (edgetrunc[i, 0] >= xmin && edgetrunc[i, 0] < xmin++ && edgetrunc[i, 1] >= ymin && edgetrunc[i, 1] < ymin++)
{
block[blockIndex] = true;
break;
}
}
}
}
heres the problem though, i put a breakpoint on the second for loop(the xmin loop) and started to iterate it, and the value of xmin jumped from 0 to 320 on the first iteration, and after that stayed there and ymin alone changed on each iteration. Am i going cray? what did i do wrong?
PS i even tested this and i got the same problem:
for (int ymin = 0;ymin < depthFrame.Height;ymin += dely)
{
for (int xmin = 0; xmin < depthFrame.Width; xmin += delx)
{
}
}
EDIT:
figured it out, it was strange, apparantly it had to do with the way i was trying to find block index. To fix it, i initialized blockIndex to 0 outside the for loops and put blockIndex++ after the 3rd for loop, thanks for the help anyways =)
int blockIndex = 0;
bool[] block = new bool[(depthFrame.Width/delx)*(depthFrame.Height/dely)];
for (int ymin = 0;ymin < depthFrame.Height;ymin += dely)
{
for (int xmin = 0; xmin < depthFrame.Width; xmin += delx)
{
for (int i = 0; i < edgeIndex; i++)
{
if ((edgetrunc[i, 0] >= xmin) && (edgetrunc[i, 0] < (xmin + delx)) && (edgetrunc[i, 1] >= ymin) && (edgetrunc[i, 1] < (ymin + dely)))
{
block[blockIndex] = true;
break;
}
}
blockIndex++;
}
}

Instead of using xmin++ and ymin++ I think you probably meant to use xmin+1 and ymin+1. ++ will change the value in the variable.

On your first inner loop iteration, the following gets run:
xmin++
as part of the if statement in the innermost loop. This gets executed 320 times, hence your value. One the second iteration,
edgetrunc[i, 0] >= xmin
will be false, and so the xmin++ line will not be executed. In general, you should avoid using mutation statements like xmin++ inside if statements. Refactor that out, and see if it fixes your problem

The reason it's jumping up like that is because you have xmin++ in the if statement inside your inner loop.
This could quite easily drive the value of xmin up quickly, depending on the value of edgeIndex.
x++ increments x then uses its old value. I think what you need is simply x+1 which uses the value plus one, without changing the value.
Ditto for the ymin++ in there as well.
In other words, it probably should be:
if (edgetrunc[i, 0] >= xmin && edgetrunc[i, 0] < xmin + 1 &&
edgetrunc[i, 1] >= ymin && edgetrunc[i, 1] < ymin + 1)

Related

Efficient way to find neighboring cells in a 2d array

I have a 2d array of class Tiles. While creating the playfield I have to generate all directly neighboring cells (horizontally, vertically, diagonally). I start by generating the field filling up each cell with a new Tile, than (when that is done) I loop through the 2d array to calculate the neighbors using this piece of loop:
int dnDistance= 1; //Direct Neighbor Distance.
for (int iMapY = 0; iMapY < playfieldHeight; iMapY++)
{
for (int iMapX = 0; iMapX < playfieldWidth; iMapX++)
{
for (int yOffset = -dnDistance; yOffset <= dnDistance; yOffset++)
{
for (int xOffset = -dnDistance; xOffset <= dnDistance; xOffset++)
{
if ((iMapX + xOffset >= 0 && iMapX + xOffset < playfieldWidth) && (iMapY + yOffset >= 0 && iMapY + yOffset < playfieldHeight))
{
if (!(yOffset == 0 && xOffset == 0))
{
playfieldTiles[iMapX, iMapY].dnTiles.Add(playfieldTiles[iMapX + xOffset, iMapY + yOffset]);
}
}
}
}
}
}
Using this method, I have to loop through the entire 2d array a second time, creating a for loop, in a for loop, in a for loop, in a for loop which sometimes is quite unclear. There has to be a better way for this, right?
I found a post that looks to be similar but not quite the same, or I don't understand it properly:
When it just works then it's fine !
Here's a little optimization that makes it easier to debug:
var playfieldHeight = 5;
var playfieldWidth = 5;
var playfieldTiles = new byte[playfieldWidth + dnDistance * 2, playfieldHeight + dnDistance * 2];
var len1 = playfieldWidth * playfieldHeight;
var len2 = dnDistance * 2 + 1;
for (var i = 0; i < len1; i++)
{
var ix = i % playfieldWidth;
var iy = i / playfieldWidth;
for (var j = 0; j < len2 * len2; j++)
{
var jx = j % len2 - dnDistance;
var jy = j / len2 - dnDistance;
Console.WriteLine($"x1: {ix}, y1: {iy}, x2: {jx}, y2: {jy}");
}
}
You now have only 2 loops, the field and the neighbors.
You could further optimize it with a single for but I believe readability will decrease (inside the loop).

Using an IF statement inside loop vs outside the loop

i have a program with a nested nested nested loop (four loops altogether). I have a Boolean variable which i want to affect the code in the deepest loop and in the first nested loop a small amount. My dilemma is, i don't really want to have the if else statement put inside the loops as i would have thought that would check the Boolean's state every iteration using extra time to check the statement, and i know that the Boolean's state would not change when the loop starts. This lead me to think it would be better to place the if else statement outside the loops and just have my loops code slightly changed, however, this also looks messy there is a lot of repeated code.
One thing i thought might work, but of which i have little experience using, is a delegate, i could simply put some of the code in a method and then create a delegate, depending on the state of betterColor i could then assign that delegate methods with the different code on them beforehand, but this also seems messy.
Below is what i am trying to avoid as i thhought it may slow down my algorithm:
for (short y = 0; y < effectImage.Height; y++)
{
int vCalc = (y <= radius) ? 0 : y - radius;
for (short x = 0; x < effectImage.Width; x++)
{
int red = 0, green = 0, blue = 0;
short kArea = 0;
for (int v = vCalc; v <= y + radius && v < effectImage.Height; v++)
{
int calc = calcs[(y - v) + radius];
for (int h = (x <= calc || calc < 0) ? 0 : x - calc; h <= x + calc && h < effectImage.Width; h++)
{
if (betterColor == true)
{
red += colorImage[h, v].R * colorImage[h, v].R;
green += colorImage[h, v].G * colorImage[h, v].G;
blue += colorImage[h, v].B * colorImage[h, v].G;
kArea++;
}
}
}
if (betterColor == true)
effectImage.SetPixel(x, y, Color.FromArgb(red / kArea, green / kArea, blue / kArea));
else
effectImage.SetPixel(x, y, Color.FromArgb(Convert.ToInt32(Math.Sqrt(red / kArea)), Convert.ToInt32(Math.Sqrt(green / kArea)), Convert.ToInt32(Math.Sqrt(blue / kArea))));
}
if (y % 4 == 0) // Updates the image on screen every 4 y pixels calculated.
{
image.Image = effectImage;
image.Update();
}
}
And here is what my code now looks like:
if (betterColor == true)
{
for (short y = 0; y < effectImage.Height; y++)
{
int vCalc = (y <= radius) ? 0 : y - radius;
for (short x = 0; x < effectImage.Width; x++)
{
int red = 0, green = 0, blue = 0;
short kArea = 0;
for (int v = vCalc; v <= y + radius && v < effectImage.Height; v++)
{
int calc = calcs[(y - v) + radius];
for (int h = (x <= calc || calc < 0) ? 0 : x - calc; h <= x + calc && h < effectImage.Width; h++)
{
red += colorImage[h, v].R * colorImage[h, v].R;
green += colorImage[h, v].G * colorImage[h, v].G;
blue += colorImage[h, v].B * colorImage[h, v].G;
kArea++;
}
}
effectImage.SetPixel(x, y, Color.FromArgb(Convert.ToInt32(Math.Sqrt(red / kArea)), Convert.ToInt32(Math.Sqrt(green / kArea)), Convert.ToInt32(Math.Sqrt(blue / kArea))));
}
if (y % 4 == 0) // Updates the image on screen every 4 y pixels calculated.
{
image.Image = effectImage;
image.Update();
}
}
}
else
{
for (short y = 0; y < effectImage.Height; y++)
{
int vCalc = (y <= radius) ? 0 : y - radius;
for (short x = 0; x < effectImage.Width; x++)
{
int red = 0, green = 0, blue = 0;
short kArea = 0;
for (int v = vCalc; v <= y + radius && v < effectImage.Height; v++)
{
int calc = calcs[(y - v) + radius];
for (int h = (x <= calc || calc < 0) ? 0 : x - calc; h <= x + calc && h < effectImage.Width; h++)
{
red += colorImage[h, v].R;
green += colorImage[h, v].G;
blue += colorImage[h, v].B;
kArea++;
}
}
effectImage.SetPixel(x, y, Color.FromArgb(red / kArea, green / kArea, blue / kArea));
}
if (y % 4 == 0) // Updates the image on screen every 4 y pixels calculated.
{
image.Image = effectImage;
image.Update();
}
}
}
In terms of what the code does, it is a box blur that uses a circular kernal.
Moving the if out of the loop, and effectively duplicating the whole looping code is not really worth it. So if you have code like this:
for (i …)
{
if (something)
DoX(i);
else
DoY(i);
}
Then you should not replace it by this:
if (something)
{
for (i …)
DoX(i);
}
else
{
for (i …)
DoY(i);
}
Doing so will only make the code a lot more difficult to read and to maintain. One first need to figure out that this is actually the same code that’s being executed for each case (except that one tiny difference), and it’s super difficult to maintain once you need to change anything about the loop since you need to make sure that you edit both cases properly.
While in theory, performing a single check vs. performing that check N times is obviously faster, in practice, this rarely matters. If-branches that rely on a constant boolean are super fast, so if you calculate the condition outside of the loop (in your case betterColor is set outside the loop), then the performance difference will not be noticeable at all. In addition, branch prediction will usually make sure that there is no difference at all in these cases.
So no, don’t rewrite that code like that. Keep it the way that is more understandable.
In general, you should avoid these kind of micro optimizations anyway. It is very likely that you algorithm has much slower parts that are much more relevant to the overall performance than small constructs like that. So focusing on those small things which are already very fast will not help you make the total execution faster. You should only optimize things that are an actual performance bottleneck in your code, where a profiler showed that there is a performance issue or that optimizing that code will actively improve your performance. And stay away from optimizations that make code less readable unless you really need it (in most cases you won’t).
The way i see it, the code is not equivalent (in your first example if betterColor is false, nothing happens in the innermost loop).
But isn't this micro-optimizing?
You could probably do something with creating a function with a Func<> as argument for the innermost loop. And then pass the correct func depending on the betterColor value.
I.E. Blur(betterColor?FuncA:FuncB);
Although I don't think it will be faster then a boolean check... But that's my feeling.

Getting incorrect mathematical value after Matlab code converted to C#

I am using a method which was generated using the TableCurve program and written in Matlab. I am trying to convert the method into C# to use in my project but it is returning incorrect values. I think I have narrowed down the problem to a particular spot, the original code is
iv=1;
for j=1:1:tcnt
for m=j:-1:1
v(iv)=tx(m)*ty(j-m+1);
iv=iv+1;
end
end
where tx, ty, and v are lists of numbers and iv is a counter. and I have translated it into
n = 0;
for (int j = 1; j <= tcnt; j++)
{
for (int m = j; m >= 1; m--)
{
v[n] = tx[m - 1] * ty[j - m];
n++;
}
}
Does anyone see a problem with my indices? because I do not. If there is no problem with my indices I will edit this question to try and locate the actual problem area.
Edit
This is the entire working Matlab code (after variables are set up)
tx(1)=1.0;
ty(1)=1.0;
tx(2)=x;
ty(2)=y;
for j=2:1:tcnt-1
tx(j+1)=2*x*tx(j)-tx(j-1);
ty(j+1)=2*y*ty(j)-ty(j-1);
end
iv=1;
for j=1:1:tcnt
for m=j:-1:1
v(iv)=tx(m)*ty(j-m+1);
iv=iv+1;
end
end
z=0.0;
for j=1:1:order+1
z = z + p(j)*v(j);
end
And this is my C# code
tx[0] = 1.0;
ty[0] = 1.0;
tx[1] = x;
ty[1] = y;
for (int j = 2; j <= tcnt; j++)
{
tx[j] = 2 * x * tx[j - 1] - tx[j - 2];
ty[j] = 2 * y * ty[j - 1] - ty[j - 2];
}
n = 0;
for (int j = 1; j < tcnt; ++j)
{
for (int m = j; m >= 1; --m)
{
v[n] = tx[m] * ty[j - m + 1];
n++;
}
}
z = 0.0;
for (int j = 0; j <= order; j++)
{
z += constantList[j] * v[j];
}
What the bleep are you doing fitting data with a Chebyshev polynomial? Use a Fourier series, you already have the equation written out and tested to everyone's satisfaction. And the equation is bounded to the curve so you don't have to worry about discontinuities outside the range you have test data for. Hey, I have a good idea... I will do that.
The only difference I can see is that matlab indices start at 1, while c# indices start at 0, so the following should be equivalent:
iv=1;
for (int j = 1; j < tcnt; ++j) {
for (int m = j; m >= 1; --m) {
v[iv-1] = tx[m] * ty[j-m+1];
iv++;
}
}
Also, the first matlab loop runs from 2 to tcnt - 1, while the C# version runs from 2 to tcnt.

Checkers Board Assistance

I'm just wondering if there is a simpler way of doing this:
for (int i = 0; i < 1; i++)
{
for (int j = 0; i < 8; j+2)
{
board[ i, j ] = 2;
board[( i + 1 ), j ] = 2;
board[( i + 2 ), j ] = 2;
}
}
What I'm trying to do is place checkers pieces on the actual checkers board. So this is to place the black pieces on the top.
P.S. If you could also give me some help on the bottom set of pieces(white).
Apart from fixing the loop you could otherwise explicitly place the pieces, makes it more readable
int[,] board = new[,]{{1,0,1,0,1,0,1,0},
{0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0},
{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},
{0,1,0,1,0,1,0,1},
{1,0,1,0,1,0,1,0},
{0,1,0,1,0,1,0,1}};
Modulo will do the trick but i think that TonyS's anwser was my first reaction and I would prefer that insteed the one shown below.
char[,] board = new char[8,8];
private void InitializeBoard()
{
string BoardRepresentation = "";
//for every board cell
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
//initialize board cell
board[i, j] = '0';
if (j <= 2)//black top
{
//Modulo is the trick
if ((j - i) == 0 || ((j - i) % 2) == 0)
{
board[i, j] = 'B';
}
}
else if (j >= 5) //white bot
{
if ((j - i) == 0 || ((j - i) % 2) == 0)
{
board[i, j] = 'W';
}
}
}
}
for (int j = 0; j < 8; j++)
{
for (int i = 0; i < 8; i++)
{
BoardRepresentation += board[i, j] + " ";
}
BoardRepresentation += Environment.NewLine;
}
}
You missed to tell us what exactly is it that you want to achieve. I see several big errors in your code, so I'll assume that you don't have full grasp of how for loop works. I hope it's not too presumptuous that I'm trying to explain it here
For loop
For loop is used to execute same portion of code several times. How many times it will be executed depends on conditions you set. Most often, you will see it in this format:
for (int i = 0; i < n; i++)
{
// Some code
}
This for loop executed code within the brackets ({ and }) n times. This is not only way to define a loop. More thorough definition of a loop is following:
for (<initialization>; <condition>; <afterthought>)
Initialization - You can some variables needed for looping. This is executed once before code within the loop is executed first time. This is optional, and you can leave it empty and use variable declared before in condition.
Condition - This is executed before each execution of code within the loop. If condition expression evaluates to true, loop is executed. Once loop is executed and afterthought is executed, condition is evaluated again and again until it evaluates to false. Condition is also optional. If you leave it out, in C# loop will be executed again until you break the loop in a different way.
Afterthought - This is executed each time code within the loop is finished executing. This is usually used to increment a variable on which loop depends. This is also optional.
Fixing your code
I assume you wanted to mark fields in a 8x8 matrix like in a checkerboard, although this is not stated in your question. You could do it this way:
// For each row in a board (start with 0, go until 7, increase by 1)
for (int i = 0; i < 8; i++)
{
// start coloring the row. Determine which field within the row needs
// to be black. In first row, first field is black, in second second
// field is black, in third row first field is black again and so on.
// So, even rows have black field in first blace, odd rows have black
// on second place.
// We calculate this by determining division remained when dividing by 2.
int firstBlack = i % 2;
// Starting with calculated field, and until last field color fields black.
// Skip every second field. (start with firstBlack, go until 7, increase by 2)
for (int j = firstBlack; j < 8; j += 2)
{
// Color the field black (set to 2)
board[i][j] = 2;
}
}
You can see my comments inline.
Big errors in your code
// This loop would be executed only once. It goes from 0 to less than 1 and is increased
// after first execution. You might as well done it without the loop.
for (int i = 0; i < 1; i++)
{
// This doesn't make sense, because you use i in condition, and initialize
// and update j.
// Also, you are trying to update j, but you are not doing so. You are not
// assigning anything to you. You should do j+=2 to increase by two. Or you
// can do j = j + 2
for (int j = 0; i < 8; j+2)
{
// I didn't really understand what you were trying to achieve here
board[ i, j ] = 2;
board[( i + 1 ), j ] = 2;
board[( i + 2 ), j ] = 2;
}
}

creating a random (Gantt-ish) chart

I'm trying to write a test for one of my audio programs, and I'm having trouble wrapping my brain around this test setup. First, I've got a table of 60 rows by 10000 columns that needs to be filled. Each cell has a value of ON, OFF, or LEFT (meaning I have the same value as my nearest ON/OFF to my left). I want a random twenty to forty rows to be on at any given time. Each has to be on for a random 6 to 200 cells. The commands to set ON or OFF have to be ordered by row then column. I'm picturing a sparse dictionary coming out with a coordinate key and on/off value. What I don't understand is how store my ON/OFF cells such that I can easily determine if my current row is ON or OFF. Help? Thanks for your time.
After further thought on this, I realized I could do it in two passes. Here's what I ended up with. Feel free to comment on this approach:
var table = new byte[60, 10000];
for(int i = 0; i < 60; i++)
{
// we want at least half the row to be blank
int j = 0;
while(j < 10000)
{
var width = rand.Next(7, 200);
j += width * 2;
var vol = (byte)rand.Next(50, 125);
for(int k = j - width; k < Math.Min(10000, j); k++)
table[i, k] = vol;
}
}
var midiEvents = new List<BASS_MIDI_EVENT>();
midiEvents.Add(new BASS_MIDI_EVENT(BASSMIDIEvent.MIDI_EVENT_PROGRAM, 0, 0, 0, 0));
for(int j = 0; j < 10000; j++)
{
for(int i = 0; i < 60; i++)
{
var cur = (int)table[i, j];
var left = j > 0 ? table[i, j - 1] : 0;
if(cur > 0 && left == 0)
{
cur <<= 8;
cur |= i + 33;
midiEvents.Add(new BASS_MIDI_EVENT(BASSMIDIEvent.MIDI_EVENT_NOTE, cur, 0, j, 0));
}
else if(cur == 0 && left > 0)
{
midiEvents.Add(new BASS_MIDI_EVENT(BASSMIDIEvent.MIDI_EVENT_NOTE, i + 33, 0, j, 0));
}
}
}

Categories