Reputation: 71
How would I modify this for-loop so that it counts up for positive values of Step
, but counts down for negative values of Step
?
For Step = 2
, the expected output is 2 4 6 8 10
For Step =- 2
, the expected output is 10 8 6 4 2
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = 2;
for ( int i = Lower; i <= Upper; i += Step )
{
Console.Write(i + " ");
}
Upvotes: 3
Views: 913
Reputation: 535
for(int i=Step>0?Lower:Upper; Step>0? i<=Upper: i>= Lower; i+=Step)
{
Console.Write(i + " ");
}
@john All you need to update the looping conditions.
Upvotes: 0
Reputation: 8805
Just obey the KISS principle.
You can just put the logic into the initialiser and the condition of the for
statement:
public static void ForLoopWithDirectionBasedOnStep(int minValue, int maxValue, int step)
{
// Avoid obvious hang
if ( step == 0 )
throw new ArgumentException("step cannot be zero");
// ( initialiser ; condition ; iterator )
for ( int i = step > 0 ? minValue : maxValue; minValue <= i && i <= maxValue; i += step )
Console.Write(i + " ");
}
so:
ForLoopWithDirectionBasedOnStep(minValue: 2, maxValue: 10, step: 2)
returns:
2 4 6 8 10
ForLoopWithDirectionBasedOnStep(minValue: 2, maxValue: 10, step: -2)
returns:
10 8 6 4 2
as desired.
The initialiser sets the start value
int i = step > 0 ? minValue : maxValue;
by using the conditional operator and is equivalent to
int i;
if ( step > 0 )
i = minValue;
else
i = maxValue;
The condition
minValue <= i && i <= maxValue
simply checks that the loop variable is within the range [minValue, maxValue].
Note that bad inputs are handled automatically because (emphasis mine):
The condition section, if present, must be a boolean expression. That expression is evaluated before every loop iteration.
so something like ForLoopWithDirectionBasedOnStep(minValue: 10, maxValue: 0, step: -2)
which would count down from 0
to 10
doesn't print anything because, since 0 < 10, the body of the for
statement is never executed.
Upvotes: 3
Reputation: 2200
You can do two for loops based on the sign of the step
variable:
static void Main(string[] args)
{
int lower = 2;
int upper = 10;
int step = -2;
if (Math.Sign(step) == 1)
{
for (int i = step; i < upper; i += step)
{
Console.WriteLine(string.Format("{0}", i));
}
}
else if (Math.Sign(step) == -1)
{
for (int i = upper; i >= lower; i += step)
{
Console.WriteLine(string.Format("{0}", i));
}
}
Console.ReadLine();
}
}
Upvotes: 1
Reputation: 43320
You need a pre-processing step to change the comparison in the for loop as well as its limits
int Lower = 2;
int Upper = 10;
int Step = -2;
Func<int, bool> comparator = (j) => j <= Upper;
if (Step < 0)
{
var temp = Lower;
Lower = Upper;
Upper = temp;
comparator = (j) => j >= Upper;
}
for(int i=Lower; comparator(i); i+=Step)
{
Console.Write(i + " ");
}
Upvotes: 2
Reputation: 5853
You can make a Func delegate to check if the step is negative and invert the bound checking condition.
Here's a sample:
class Program
{
public static void Print(int Lower, int Upper, int Step)
{
Func<int, bool> checkBounds = (i) => i <= Upper;
if (Step < 0)
{
Swap(ref Lower, ref Upper);
checkBounds = (i) => i >= Upper;
}
for (int i = Lower; checkBounds(i); i += Step)
Console.Write($"{i} ");
}
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = -2;
Print(Lower, Upper, Step);
}
}
Upvotes: 0
Reputation: 666
Note that this code is untested but the idea is to use a Predicate<T>
for the loop and switching Upper and Lower if step is negative
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = 2;
if(step < 0){ int temp = Lower; Lower = Upper; Upper = temp;}
Predicate<int> LoopPred = (i =>
{
if(Step < 0)
return i >= Upper;
return i <= Upper;
})
for(int i=Lower; LoopPred(i); i+=Step)
{
Console.Write(i + “ “);
}
Upvotes: 0