Home > Back-end >  For Loop that counts up and down from a start index inside range
For Loop that counts up and down from a start index inside range

Time:06-24

I'm having trouble developing a for-loop that starts at a given integer (start) and then counts up and down from this starting point inside a given range (min to max). I want the result to be in order by distance to the given start. If a for-loop is not the right tool here, i am open for other suggestions!

Since this is hard to explain i have a example down below:

var start = 4;
var max = 10;
var min = 0;
var stepSize = 1;
for(var i=startIndex; i>=min && i<=max; ???) {
  Console.WriteLine(i)
}

The result should look like this:

4 5 3 6 2 7 1 8 0 9 10

The really tricky part for me is the end where the alternation has to stop in order to reach the max value of 10 and not go below 0 in the meantime.

I started experimenting and had a solution that would work for the first bit:

const int start = 4;
const int stepSize = 1;
    
for (var (i,j,k) = (start,1,5); Math.Abs(j)<=11; k=(k j),j=-j-Math.Sign(j)*stepSize,i=(k (start-5))) {
  Console.WriteLine(i);
}

This works fine for the first part where alternation is needed, but it breaks once the alternation needs to stop. The result from this experiment is:

4 5 3 6 2 7 1 8 0 9 -1

CodePudding user response:

A simple but elegant solution could generate the number sequence you want like so:

static IEnumerable<int>
UpDownCount(int start, int lower, int upper)
{
    int i = start, j = start;
    yield return start;
    while (true)
    {
        bool ilimit =   i <= upper,
            jlimit = --j >= lower;
        if (ilimit)
            yield return i;
        if (jlimit)
            yield return j;
        if (!(ilimit || jlimit))
            yield break;
    }
}

Then you can use that sequence with LINQ or a simple foreach loop:

foreach (int i in UpDownCount(4, 0, 10))
    Console.WriteLine(i);

CodePudding user response:

Here it is with a for loop, but like others have already alluded to, I think other structures are better suited for your task:

  public static void Main() {
    int start = 4;
    int max = 10;
    int min = 0;
    int stepSize = 1;
    for(int i=start, j=start; i>=min || j<=max; i-=stepSize, j =stepSize) {
      if (i==start) {
        Console.Write(i   " ");
      }
      else {
        if (j <= max) {
          Console.Write(j   " ");
        }
        if (i >= min) {
          Console.Write(i   " ");    
        }        
      }      
    }
  }

CodePudding user response:

The sequence you are after:

4 5 3 6 2 7 1 8 0 9 10

Could be specified as the following:

4 - 3 - 2 - 1 - 0
- 5 - 6 - 7 - 8 - 9 10 
- - - - - - - - - - --
4 5 3 6 2 7 1 8 0 9 10

Which using something like MoreLinq, could be expressed like this:

Sequence(4, 0).Interleave(Sequence(5, 10))

Obviously, you control the start, max and min by controlling the values of both sequences. So, say you want to start from 7, going up and down towards 1 as the minimum value, and 14 as the maximum. The call would be like:

Sequence(7, 1).Interleave(Sequence(8, 14))

Lastly, this also allows you to easily change from a "up-down" to a "down-up" by swapping the intervals. Using the example above:

Sequence(8, 14).Interleave(Sequence(7, 1))
  • Related