I'm writing a graphics program in C# and I couldn't figure out a good way to run a for loop between two values, where either one may be larger or smaller than the other.
To demonstrate, the following code works perfectly when X2>X1:
for (int x = X1; x<=X2; x++) {
//code
}
However, it fails when X2<X1. What I want to happen in this situation is that the loop starts at X1 and goes backwards until X2.
I since I'm doing a graphics program, I can't simply swap X1 and X2 when X2<X1, as this would mean swapping their associated Y values, which could produce the same problem just for Y values. The loop must always start at X1, it's the direction(+/-) that needs to change, not the order of values.
I've thought of a few solutions however they all have flaws, it's worth noting that X1 will never equal X2.
#1: Replicate loop
if (X2<X1) {
for (int x = X1; x>=X2; x--) {/*code*/}
} else {
for (int x = X1; x<=X2; x++) {/*code*/}
}
Unsuitable because of replicated code, especially if the "//code" section is particularly long
#2: Lots of ternaries
for (int x = X1; x!=X2+(X2<X1?-1:1); x+=(X2<X1?-1:1)) {/*code*/}
While this code works and is concise, it's readability is terrible. Also I've seen in various places that using "not equal to" for your loop constraint is bad practice source
#3: Use a while loop
int x = X1;
while(true) {
//code
if (X2<X1) {
x--;
if (x<X2) break;
} else {
x++;
if (x>X2) break;
}
}
This solution seems very long and convoluted to perform such a simple task, in addition, use of "while(true)" is also bad practice source
I think the most readable option is to simple create/extract method from the repeating code (the first proposed version):
void ComputeRenderedStuff(int x)
{
// do your computations for x
}
if (X2<X1)
for (int x = X1; x>=X2; x--)
ComputeRenderedStuff(x);
else
for (int x = X1; x<=X2; x++)
ComputeRenderedStuff(x);
A simple solution would be to use one variable for the loop itself, and another variable for the steps:
int length = Math.Abs(x1-x2);
for(int i=0; i <= length; i++)
{
// step will go either from x1 to x2 or from x2 to x1.
int step = (x1 < x2) ? x1 + i : x2 + (length-i);
}
Of course, you can wrap the entire loop in a method, so you wouldn't have to repeat the code:
void ForLoopUnknownDirection(int start, int stop, Action<int> action)
{
int length = Math.Abs(start-stop);
for(int i=0; i <= length; i++)
{
int step = (start < stop) ? start + i : stop + (length-i);
action(step);
}
}
This way you can do whatever you want between the numbers while only writing the loop code once.
See a live demo on rextester
Simply use Math.Min() and Math.Max() to choose lower and upper boundaries.
Something like this:
int MinX = Math.Min(X1, X2);
int MaxX = Math.Max(X1, X2);
for (int x = MinX; x <= MaxX; x++) {
//code
}
Maybe extract a method like this
private static IEnumerable<int> Step(int start, int end)
{
if (start < end)
{
for (int x = start; x <= end; x++)
yield return x;
}
else
{
for (int x = start; x >= end; x--)
yield return x;
}
}
Then you can do
foreach (int x in Step(X1, X2))
{
/*code*/
}
Use a directional increment ( d in the code below )
var d = (x1 > x2) ? -1 : 1;
var i = x1;
while (i != x2)
{
//
// insert your code here
//
i = i + d;
}
Am I purdy? 😜
Why so complicated?
for (int n = 0; n < Count; n++)
{
int Index = (ascending ? n : Count - 1- n);
}
Related
I need to calculate euclidian distance for every point in matrix and store it into the List. But it works too slow. How can I get it faster?
public static char[,] fields = new char[10000, 10000]; // it contains different count of 't' and 'r' symbols
List<Tuple<int, int, double>> tuples = new List<Tuple<int, int, double>>();
for (int i = 0; i < 10000; i++)
{
for (int r = 0; r < 10000; r++)
{
if (fields[i, r] != 't')
tuples.Add(Tuple.Create(i, r, Math.Sqrt(Math.Pow(i - x, 2) + Math.Pow(r - y, 2))));
}
}
Ok, here is another hint which might help - use specific squared function instead of generic Pow
double Squared(int x) => (double)(x*x);
so code would be
Math.Sqrt(Squared(i - x) + Squared(r - y))
And another optimization might be realized if your use of the result might be converted to dealing with distance squared. E.g.
comparison far/near could be easily done with distance squared. Then, you could save on computing square root of distance squared.
UPDATE
You could save one conversion operation if you do Squared all integers and convert to doubles later just before taking square root
Along the lines
int Squared(int x) => (x*x);
and
Math.Sqrt((double)(Squared(i - x) + Squared(r - y)));
You could pre-calculate each of the squares, so each squaring calculation is performed 10000 times instead of 10000*10000 times.
public static double[] preCalcSquares(int n) {
double[] pre=new double[10000];
for (int i = 0; i < 10000; i++)
{
pre[i]=(i-n)*(i-n);
}
return pre;
}
. . .
double[] xSquares=preCalcSquares(x);
double[] ySquares=preCalcSquares(y);
for (int i = 0; i < 10000; i++)
{
for (int r = 0; r < 10000; r++)
{
if (fields[i, r] != 't')
tuples.Add(Tuple.Create(i, r, Math.Sqrt(xSquares[i] + ySquares[r])));
}
}
I attempted a simple task during learning but I'm stuck and have some weird results.
I have to write a simple method with 2 parameters 'x' and 'a'. Result of this method has to be sum of all xk/k! where k starts from 0 and goes to infinity, and 'a' is a parameter of accuracy.
Here how it looks
But I have no idea why when I'm putting Console.Write inside of loop, numbers are acting crazy and I have this for x = 2 and x = 6
Also when I'm trying to put my code into method and use result there is nothing happening.
I have another method for mathematical factorial to calculate k!.
decimal wynik = 0;
int x = 2;
int a = 6;
for (int k = 1; k > 0; k++)
{
if (Algorithms.Factorial(k) > 0)
{
wynik += Math.Round(Convert.ToDecimal(Math.Pow(x, k)) /
Algorithms.Factorial(k), a);
Console.WriteLine(wynik);
}
}
Console.WriteLine(wynik);
and Factorial method
static public int Factorial(int n)
{
int wynik = 1;
for (int i = 1; i <= n; i++)
{
wynik *= i;
}
return wynik;
}
Of course I want to end with method and returning results but for practicing I'm working in Main method
Thanks a lot for help!
Factorial grows very fast, please, look
13! = 6227020800 > int.MaxValue
that's why returning int in static public int Factorial(int n) can well lead to integer overflow and strange results.
x ** k grows fast as well (though not that fast as factorial does). Let these large numbers cancel one another:
double x = 2;
double tolerance = 0.00001;
double result = 1.0; // x**0 / 0! == 1 / 1 == 1
double term = 1.0;
for (int k = 1; term > tolerance; ++k) {
// given term = (x ** (k - 1)) / (k - 1)!
// we can compute next term as
term = term * x / k;
result += term;
}
// Let's have a look (in fact, you have Taylor serie for exp)
Console.WriteLine($"actual : {result} (+/- {tolerance:0.##############})";
Console.WriteLine($"expected : {Math.Exp(x)}"");
Outcome:
actual : 7.3890545668323435 (+/- 0.00001)
expected : 7.38905609893065
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.
I feel like I'm missing something terribly obvious, but I cannot seem to find the array pair with the lowest value.
I have an int[,] worldMapXY where a 2D map is stored, say worldMapXY[0,0] through worldMapXY[120,120]. All values of map's array are 1 (wall\invalid) or 0 (path/valid).
I'm writing a method that will find coordinates in one of the eight cardinal directions to create a spawn point. So I also have int[,] validSpotArr which has a subset of bounds of the map closest to the direction I'm setting the spawn. The values for wall/invalid locations are set to 9999, the values for path/valid locations are set to (x + y). This is all specific to the bottom left corner, nearest to [0,0], hence "BL" or "Bottom Left"
case "BL":
for (int x = (int)border + 1; x < worldX + (int)border / 4; x++)
{
for (int y = (int)border + 1; y < worldY + (int)border / 4; y++)
{
if (worldMapXY[x,y] = 0)
{
validSpotArr[x,y] = x + y;
}
else
{
validSpotArr[x,y] = 9999;
}
}
}
What I can't quite wrap my head around is how to determine the coordinates/index of validSpotArr with the lowest value in such a way that I could pass those as separate x and y coordinates to another function (to set the spawn point). I suspect there's a lambda operator that may help, but I literally don't understand lambdas. Clearly that needs to be my next point of study.
E.g. - if validSpotArr[23, 45] = 68, and 68 is the lowest value, how do I set x=23 and y=45?
Edit: I tried messing around with something like this, but it isn't right:
Array.IndexOf(validSpotArr, validSpotArr.Min());
While not precisely an answer to your question, in a strictly given situation I'd probably go for finding those from within the cycles, i.e.
int minValidSpot = int.MaxValue, minX, minY;
for (int x = (int)border + 1; x < worldX + int(border) / 4; x++)
{
for (int y = (int)border + 1; y < worldY + int(border) / 4; y++)
{
if (worldMapXY[x,y] = 0)
{
validSpotArr[x,y] = x + y;
}
else
{
validSpotArr[x,y] = 9999;
}
if ( minValidSpot > validSpotArr[x,y] )
{
minValidSpot = validSpotArr[x,y];
minX = x;
minY = y;
}
}
}
Other than that, if looking for some kind of more universal solution, I'd probably just flatten that array, the maths for index conversion (nD<=>1D) are pretty simple.
I am using this code to solve problem. 4 on Project Euler. The problem reads:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
I have tried to solve the problem. My code returns a palindrome number and a fairly big one too. But it is incorrect. I have also found a correct solution at MathBlog.dk. But what is wrong with my code? --
long result = 0;
for (long x = 100; x <= 999; x++)
{
for (long y = 100; y <= 999; y++)
{
long num = x * y;
if (num.ToString() == StringFunctions.ReverseString(num.ToString()))
{
result = num;
}
}
}
Console.WriteLine("Result : {0}", result);
The StringFunctions.RevereString function is as follows:
public static class StringFunctions
{
public static string ReverseString(string s)
{
string result = "";
for (int i = s.Length - 1; i >= 0; i--)
{
result += s.Substring(i, 1);
}
return result;
}
}
My code returns 580085 but the correct answer is 906609. I don't want to know about better solutions. I just want to know why my code isn't working.
Any help will be much appreciated. Thanks in advance.
Your result is storing the last palindrome number obtained from the loop but not the largest one.
Both the variables X and Y iterate from 100 to 999
Imagine a case when (assuming all obtained numbers are palindromes) x = 500 and y = 500. It will execute earlier than x = 990 and y = 100. But in the earlier case the palindrome is larger but your code stores the smaller one. Use an if condition to get the largest palindrome:
long result = 0;
for (long x = 100; x <= 999; x++)
{
for (long y = 100; y <= 999; y++)
{
long num = x * y;
if (num.ToString() == StringFunctions.ReverseString(num.ToString()))
{
if(result < num)
{
result = num;
}
}
}
}
Console.WriteLine("Result : {0}", result);