1

I have a one-dimensional array, and I need to run operations on it based on the adjacents cells of every cell.

For instance:

To run the operations on the first cell, I'll need to access the last cell and the second.

The second cell, I'll need to access the first cell and the third cell.

The last cell, I'll need to access the first cell and the one before the last cell.

My code so far is:

public static int[] firstRule(int[] numberArray)
{
    for (int i = 0; i < numberArray.Length; i++)
    {
        if (numberArray[numberArray.Length - 1 - i] == numberArray[i] + 1 
            && numberArray[i + 1] == numberArray[i] + 1)
        {
            numberArray[i] = numberArray[i] - 1;
        }
    }
    return numberArray;
}

But the problem with my approach is that it would only work for the first cell, as it would take the last cell and the second cell correctly, but after that, everything would fall apart. I don't like posting without a lot of code but I have no clue how to follow this up.

I am trying to achieve the following:

Those values are numbers ranging from 0 to 3. If both the cell before and the cell after is the same number, I want to change it to x + 1
For instance: suppose I have 1 0 1 2 2. I would want to change 0 to 1. As the neighbor cells are both 0.

8 Answers8

4

Just keep it simple and use variables to calculate the left and right cell indices. Inside your for loop you can do this...

var leftCell = i - 1;
if (leftCell < 0)
{
    leftCell = numberArray.Length - 1; // Wrap around to the end...
}

var rightCell = i + 1;
if (rightCell > numberArray.Length - 1)
{
    rightCell = 0;  // Wrap back around to the beginning...
}


// Now you can update your original code to use these computed indices...
if (numberArray[leftCell] == numberArray[i] + 1 
    && numberArray[rightCell] == numberArray[i] + 1)
{
    numberArray[i] = numberArray[i] - 1;
}
David
  • 34,223
  • 3
  • 62
  • 80
  • 1
    Maybe I' missing something, but couldn't you refer to the left, current, and right simply by using the mod operator? That is, prev: (i-1) % arrayLength, current: i, next: (i+1)%arrayLength – Tung Sep 16 '15 at 19:28
  • @Tung (i-1 + arrayLength) % arrayLength is more accurate for the left index. Try i=0 – Seven Sep 16 '15 at 19:37
  • @Seven, true C#'s % returns the remainder and not strictly "modulo". – Tung Sep 16 '15 at 22:14
  • hmm.. based on the question, the value of `numberArray[i]` shouldn't matter at all in determining whether it should be incremented, (let alone the value being increased).. `numberArray[Leftcell] == numberArray[Rightcell]` should be all that is needed,.. **but** I'm thinking the OP mistakenly forgot to specify it in his question.. Still, I would update this answer to include the loop, declaring the variables outside of the loop; the do a check, assignment vs this assignment, check, (conditional) assignment. pattern you have going here. – Brett Caswell Sep 17 '15 at 15:42
3

Try this out:

var len = numberArray.Length;
for (int i = 0; i < len; i++)
{
    var leftIndex = (i - 1 + len) % len;
    var rightIndex = (i + 1) % len;

    // do your stuff with numberArray[leftIndex] and numberArray[rightIndex] 
}

% is mod operator. % len allows you to stay in range 0..len-1, so you can walk through array as if it has become 'cyclic'

Community
  • 1
  • 1
Seven
  • 805
  • 12
  • 17
  • ... what is the point of doing 2 mod operations on each iteration?.. to avoid doing two checks of each iteration? `i == 0 ? len - 1: i -1` `i == len ? 0 : i - 1` – Brett Caswell Sep 16 '15 at 20:07
  • @BrettCaswell just to keep it simple and the most readable. Not always the fastest solution is the best solution. – Seven Sep 16 '15 at 20:12
3

From your comments.

Those values are numbers ranging from 0 to 3. If both the cell before and the cell after is the same number, I want to change it to x + 1
For instance: suppose I have 1 0 1 2 2. I would want to change 0 to 1. As the neighbor cells are both 0.

I would create a new array, populate it with the values of the existing array and then change the values of the new array according to the results of the value in the existing array.

Edit as Op is getting wrong values I suspect you may not be copying the array correctly instead:

Existing Array array // The array you are passing in as parameter.

Declare a new empty array:

int[] newArray;
int size = array.length;

for(int i =1; i<size-1;i++){

    if(array[i-1]==array[i+1])){
        newArray[i]=array[i]+1;
    }
    else{
        newArray[i]=array[i];
    }

}
if(array[size-1]==array[0]){
    newArray[size]= array[size]+1;
}
else{
        newArray[i]=array[i];
    }
if(array [size]==array[1]){
    newArray[0]= array[0]+1;
}
else{
        newArray[i]=array[i];
    }

if there is a limit to the number and it reverts to zero after 2, then just do a simple if test for that.

1
public static void firstRule(int[] numberArray)
{
    for (int i = 0; i < numberArray.Length; i++)
    {
        int? prevElement = i == 0 
            ? numberArray[numberArray.Length-1]
            : numberArray[i - 1];

        int? nextElement = i == numberArray.Length -1
            ? numberArray[0]
            : numberArray[i + 1];

        Console.WriteLine(
            String.Format("Prev: {0}; Current: {1}; Next: {2}",
                prevElement,
                numberArray[i],
                nextElement)
            );
    }
}

And then calling firstRule(new int[]{ 1, 2, 3 }); prints:

Prev: 3; Current: 1; Next: 2
Prev: 1; Current: 2; Next: 3
Prev: 2; Current: 3; Next: 1
Ortiga
  • 8,455
  • 5
  • 42
  • 71
1
int[] arr = new int[] { 1, 2, 3, 4, 5 };

var triples = arr.Select((n, i) =>
{
    if (i == 0)
        return Tuple.Create(arr[arr.Length - 1], arr[0], arr[1]);
    else if (i == arr.Length - 1)
        return Tuple.Create(arr[i - 1], arr[i], arr[0]);
    else
        return Tuple.Create(arr[i - 1], arr[i], arr[i + 1]);
});

foreach (var triple in triples)
{
    Console.WriteLine(triple.Item1 + " " + triple.Item2 + " " + triple.Item3);
}
Alexander Petrov
  • 13,457
  • 2
  • 20
  • 49
1

OPTION 1

assign regardless

    public static int[] firstRule(int[] numberArray)
    {
        int left,right;
        for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
        {                
            left = (i == 0) ? max : i - 1; 
            right = (i == max) ? 0 : i + 1;

            numberArray[i] = (numberArray[left] == numberArray[right]) ? numberArray[i] + 1 : numberArray[i]; //always peforms an assignment;
        }
        return numberArray;
    }

OPTION 2

conditionally assign

    public static int[] secondRule(int[] numberArray)
    {
        int left,right;
        for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
        {   
            left = (i == 0) ? max : i - 1; 
            right = (i == max) ? 0 : i + 1;

            if (numberArray[left] == numberArray[right])
            {
               numberArray[i]++;
            }
        }
        return numberArray;
    }

OPTION 3

left and right are only used 1 time in each iteration.. so why bother assigning them to a variable???...

    public static int[] thirdRule(int[] numberArray)
    {            
        for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
        {                
            if (numberArray[(i == 0) ? max : i - 1] == numberArray[(i == max) ? 0 : i + 1])
            {
                numberArray[i]++; // what happens if numberArray[i] is 3, should it become 4 or 0?
            }
        }
        return numberArray;
    }

OPTION 4 (UNSAFE)

unsafe - fixed - pointers

    public static int[] fourthRule(int[] numberArray)
    {
        unsafe {
            int* pointer, right, left; 

            for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
            {
                fixed (int* p1 = &numberArray[0], p2 = &numberArray[i], p3 = &numberArray[max])
                {
                    pointer = p2;
                    if (i == 0)
                    {
                        left = p3;
                        right = pointer;
                        right++;
                    }
                    else if (i == max)
                    {
                        left = pointer;
                        left--;
                        right = p1;
                    } 
                    else
                    {
                        left = pointer;
                        left--;
                        right = pointer;
                        right++;
                    }

                    if (*right == *left) {
                        *pointer = *pointer + 1;
                    }
                }
            }
        }
        return numberArray;
    }  
Brett Caswell
  • 732
  • 1
  • 4
  • 16
0

Recently came up against this myself and found this to be a solid method. `

int length = numberArray.Length; 
for (int i = 0; i < length; ++i)
{
    int iMinus = (((i - 1) % length) + length) % length;
    int iPlus = (((i + 1) % length) + length) % length;
}`
xenetics
  • 11
  • 2
-1

Something like this should work. It determines the appropriate cells for the operation in each loop and executes the operation. You didn't state what that operation was so you need to fill in the DoYourOperation method.

public static int[] processArray(int[] numberArray)
{
    for (int i= 0; i < numberArray.Length; i++)
    {
        int firstCell;
        int secondCell;
        //Check if first cell
        if(i == 0)
        { 
            firstCell = numberArray[numberArray.length-1]; //Last cell
            secondCell = numberArray[i++]; //Next cell
        } 
        //Check if last cell
        else if(i == numberArray.Length - 1)
        { 
            firstCell = numberArray[i--]; //Cell before last one
            secondCell = numberArray[0]; //First cell
        }  
        else
        {
            firstCell = numberArray[i--];
            secondCell = numberArray[i++];
        }

        DoYourOperation(firstCell, secondCell);
    }  
}
John Paul
  • 827
  • 2
  • 6
  • 16
  • You need to replace all the `i++` and `i--` calls within the loop to `i + 1` and `i - 1` because that will update the value of `i` and you don't even get the correct value returned (it returns `i` then increments or decrements). – juharr Sep 16 '15 at 19:37
  • Yes that's true although after reading the comments on the question it seems as I have misunderstood the question. – John Paul Sep 16 '15 at 19:40