Drag and Drop sequence order - c#

may be the title of the question is not adequate, here is my problem, i'll start with giving you an example :
Original Sequence :
0. Item_105
1. Item_13
2. Item_6
3. Item_14
4. Item_106
Modified Sequence :
0. Item_105
1. Item_14
2. Item_13
3. Item_6
4. Item_106
Here i must have 2 indexes :
Index1 = 3
Index2 = 1
which means that the old element 3 went to the new position 1
i'm actually working with C# language and when i drag an item to drop it in a new position sometime it gives me good indexes, sometimes not!!
this is the "for" loop i used to get the indexes :
for (int i = 0; i < stops.Count - 1; i++)
{
if (originalOrder[i] != modifiedOrder[i])
{
if (originalOrder[i] == modifiedOrder[i + 1] && index2 == -1)
index2 = i;
else if (modifiedOrder[i] == originalOrder[i + 1] && index2 == -1)
index2 = i;
if (originalOrder[i] != modifiedOrder[i + 1] && index1 == -1)
index1 = i;
}
}
So this is my problem : How to get the right indexes 1 and 2 ? I need the to do some staff later in the code, if i have the right indexes all the rest is OK!!
please can anyone help me?

For starters, the assymetry in your code looks suspicious. Without looking very much at your current code, I would assume that it might be giving you the right answer when you drag an item in one direction but not the other.
index1 = -1;
index2 = stops.Count; // This could be off by one
for (int i = 0; i < stops.Count - 1; i++)
{
// First, find the bounds of what was moved
if (originalOrder[i] != modifiedOrder[i] && index1 == -1)
{
index1 = i;
}
if (index1 != -1 && originalOrder[i] == modifiedOrder[i])
{
index2 = i-1;
// No need to look at any more items
break;
}
}
// Swap indices depending on which direction item was moved
if (originalOrder[index1] != modifiedOrder[index2])
{
int temp = index1;
index1 = index2;
index2 = temp;
}
I can't tell from your example what stops.Count represents. You'll need to ensure that index 2 is initialized to the last index.

Related

Index was outside the bounds of the array. and even my teacher doesn't know the solution

I'm trying to make a scan of an array where it follows the index with the numbers inside and I don't understand why it gives me this exception. I cant add any more details its a pretty straight forward question.
using System;
public class Program
{
public static bool IsPerfect(int[] arr)
{
int next=0, done=0,i;
while (done == 0)
{
i = arr[next];
arr[next] = 10;
next = arr[i];
if (i == 0)
done = 1;
}
for(int j = 0; j < arr.Length; j++)
if (arr[j] != 10)
return false;
return true;
}
public static void Main()
{
int[] arr = { 3, 0, 1, 4, 2 };
if (IsPerfect(arr) == true)
Console.WriteLine("is perfect");
if (IsPerfect(arr) == false)
Console.WriteLine("boooo");
}
}
You are not specifying the functioning for duplicates... Use a method to check for duplicates and as soon as you encounter a duplicate element exit the loop... It will work fine! 👍
ok for anyone intrested the problem was lying in the second if, and the "next = arr[i];" the first i changed because it made more sense and the second and main problem was the other if. because i had the second condition it ran the method twice and with the changed values it returned an error.
the solution was to put else instead.
Reverse engineering: we mark visited items and if all items are visted, then we have a "Perfect" array.
Problem: we mark item with 10 which can be an index (what if array has, say, 15 items)?
Solution: let's mark by -1 (definitely not an index - an array can have negative number of items) and check if item has been marked:
Tricky moment: we should assign -1 to the current arr[i] item but use its initial value to be assigned to i. Sure, we can save i and put it as
for (int i = 0; i >= 0 && i < arr.Length; ) {
int nextI = arr[i];
arr[i] = i;
i = nextI;
}
but let's put in a short modern way: (i, arr[i]) = (arr[i], -1);
Code:
public static bool IsPerfect(int[] arr) {
// In public method we must be ready for any input; null included
if (arr == null)
return false; // or throw new ArgumentNullException(nameof(arr));
// Do we have a valid array?
for (int i = 0; i < arr.Length; ++i)
if (arr[i] < 0 || arr[i] >= arr.Length)
return false;
// Note the condition: we read the next item - arr[i] -
// if and only if i is within range
// Note, that we have nothing to increment / decrement
for (int i = 0; i >= 0 && i < arr.Length; )
(i, arr[i]) = (arr[i], -1); // note the assignment: both i and arr[i] in one go
// We have marked all that we could.
// Do we have unmarked items?
for (int i = 0; i < arr.Length; ++i)
if (arr[i] != -1) // ... yes, we have and thus
return false; // arr is not perfect
return true;
}
Please, fiddle

C#, one-dimension wrapping array

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.
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;
}
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'
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.
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);
}
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
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;
}
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;
}`
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);
}
}

A way to shorten an if statement

I have an array of four numbers which I need to compare to another array of numbers. I should tell how many of those numbers are right placed, and how many are right numbers but not right placed.
F.eks:
Code: 1501
Guess: 1305
Right numbers: 3
Right placement: 2
The right placement is easy. But the Right Number part is a bit tricky. This is how I solved it:
//Check if number exist in context
Rn = 0;
for (int g = 0; g < 4; g++)
{
resent[g] = 6;
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if
(
guess[i] == Numbers[j]
&& guess[i] != resent[0]
&& guess[i] != resent[1]
&& guess[i] != resent[2]
&& guess[i] != resent[3]
)
{
Rn++;
resent[i] = guess[i];
}
}
}
ConsolePost("Right Numbers: " + Rn);
Is there a beter way to do this. Or is it possible to shorten this?
Like:
if(guess[i] == Numbers[j] && != resent[0-3])
{
Something;
}
You can use Any() to check if you decide to change the size of your array:
!resent.Any(c=>c==guess[i])
You can use Enumerable.Take(4) and Contains on your resent like:
!resent.Take(4).Contains(guess[i])
So your check could be:
if(guess[i] == Numbers[j] && !resent.Take(4).Contains(guess[i]))
See: Enumerable.Take<TSource> Method
Returns a specified number of contiguous elements from the start of a
sequence.
If resent size is always 4, then you can skip Take(4) and instead just use Contains like:
if(guess[i] == Numbers[j] && !resent.Contains(guess[i]))

C# runtime error: index out of range

I have to make a simple windows forms application in which the player takes turns with the computer in taking sticks (which I made out of labels which go invisible), but I am having a problem with the code for the pc as it causes a runtime error "index out of range", and I can't figure it out..
private void pcTake(int x)
{
textBox1.Text = "I take " + x;
for (int i = 0; i < labels.Count; i++)
{
if (labels[i].Visible == false && labels[i + 1].Visible == true)
{
while (x > 0)
{
if (x + i > labels.Count)
break;
labels[i + x].Visible = false;
x--;
}
break;
}
}
}
x is a random number,
labels is a list containing the labels
foreach (Control c in this.Controls)
{
if (c is Label)
{
labels.Add(c);
c.Enabled = true;
}
}
thanks in advance
You are getting the exception beause of your comparison
labels[i + 1].Visible == true
since your loop is based on < labels.Count, that means when the loop index reaches to count - 1, your condition is suppose to check array index on count (because of i + 1), since array's index is 0 based, you are getting the exception.
If you want to check the current index and later index then your loop condition should be i < labels.Count - 1 like:
for (int i = 0; i < labels.Count - 1; i++)
In C#, arrays are 0-indexed, so the last item is labels[labels.Count-1]; you should change this
if (x + i > labels.Count)
break;
into this
if (x + i > labels.Count -1)
break;

Check and calculate the values next to the current index key array in c#

if (theArray[i-1] < theArray.Length && theArray[i-1] != null)
Is what i got after some research. But it gives just gives me out of index error, because i do i-1.
But i want the if statement to check whether the key/index on i-1 exists, then do something..
See what i want to do is plus the values of the indexes next to the current index.
for (int i = 0; i < theArray.Length; i++)
{
Left = 0;
Right = 0;
if (i != 0)
{
Left = theArray[i - 1];
}
if (theArray[i + 1] < theArray.Length)
{
Right = theArray[i + 1];
}
calc = Left + Right;
output2.Text += calc + ", ";
}
So if the left is there then change the left value (default is 0, right and left), and if right is there then change the right value. And then calculate both values taken from theArray[].
E.g if its on theArray[16] it should take the left, theArray[15] and theArray[17] and plus together.
I think you are looking for:
if(i < theArray.Length)
Or possibly:
if(i < theArray.Length && theArray[i] != null)
I would normally be using i in a loop like this:
for(int i = 0; i < theArray.Length; i++)
Update:
You can't use i-1, because on the first iteration, when i == 0, this would evaluate to -1. This is an illegal index in an array.
Update 2:
I think I understand what you are trying to do now. Here is one way to do it:
for (int i = 0; i < theArray.Length; i++)
{
Left = 0;
Right = 0;
if (i > 0)
{
Left = theArray[i-1];
}
if (i < theArray.Length - 1)
{
Right = theArray[i+1];
}
calc = Left + Right;
output2.Text += calc + ", ";
}
To check if i is a valid array index, you can do this:
if(i >= theArray.GetLowerBound(0) && i <= theArray.GetUpperBound(0))
That will only be necessary in rare edge cases, however, so it's more practical to do this:
if(i >= 0 && i < theArray.Length)
Once you know that it's a valid index, you can check for null if need be.
Is your question whether the index or the array value with given index exists?
In case of array you can always be sure that index n "exists" if 0 < n < array.Length.
If you want to check for the array value, first check for (n > 0) for the index "under" and (n < array.Length) for the index "over"
I think in addition to what Oded said, the correct expression might be:
if (i < theArray.Length && i > 0 && theArray[i-1] != null)
because you are checking value at i-1 index.
From your code, it appears that "i" is one-based and your array indexes are zero-based. So you could use:
if ( (i > 0) && (i <= theArray.Length) && (theArray[i-1] != null) )

Categories