A way to shorten an if statement - c#

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]))

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

Bring multiple 2d arrays [][] on same length

i have a huge Problem when dealing with jagged arrays [][].
I wrote a program that interacts with lots of CSV-files. It will read them and then compare them. Now i have a problem if Array A has the dimension of 10 Rows and 10 Columns but Array B only has the dimension of 5 Rows and 5 Columns. I get the "out of range" on array B. This is only an example it gets even worse if i have a array which has different amount of Rows in each Column...
I tried checking for "null" but this doesnt work since i get the "out of range" once it tries to acess the field...
Now i have 2 theories to solve the problem:
A.)Check for "out of range" in Array B and if so fill Array A at the same field with a "0"
B.) Check if Array A and Array B has same dimension and if not fill the array with lesser amount with "0" so that it has the same amount
On both solutions i have absolutely no clue how to do this in C#... I am always getting the out of range...
What i currently do for 1 array is:
for (int b = CSV_Statistiken.Length - 1; b >= 0; b--)
{
for (int a = 0; a < CSV_Statistiken[b].Length; a++)
{
CSV_Statistiken[b][a] = 1;
}
}
so i get the dimension of the array and iterate through it, setting every value to 1. But how do i deal with my problem with 2 arrays?
I researched a bit but couldnt find any solution to this =/
Thanks in advance
Edit: What i am trying to do for examlple:
for (int i = 0; i < number; i++) //runs through every File existing
{
NextFile = fold.Filepath + "\\" + files[i].ToString();
file = new FileInfo(#NextFile);
max_Rows = 0;
max_Col = 0;
CSV_temp = ReadCSV(file, ref max_Rows, ref max_Col); // reads the next file to an arraay [][] and saves the size of this array in max_col/ max_rows
MAX_Col_Total = GetHighestValues(ref MAX_Col_Total, max_Col);
MAX_Rows_Total = GetHighestValues(ref MAX_Rows_Total, max_Rows);
for (int j = 0; j < MAX_Col_Total; j++) //runs thrugh the max amount of cols found
{
for (int k = MAX_Rows_Total - 1; k >= 0; k--) //runs through the max mount of rows found
{
if (CSV_temp.GetLength(0) >= j && CSV_temp.GetLength(1) >= k)//Checks if Field exists -> does NOT work!
{
if (CSV_temp[k][j] > (Threshhold))) //
{
do something
}
}
else
{
// Field doesnt exists -> do something else
}
}
}
}
You can check Lengths of two arrays in for loops:
for (int a = 0; a < array1.Length && a < array2.Length; a++)
{
for (int b = 0; b < array1[a].Length && b < array2[a].Length; b++)
{
//compare
}
}
Now your loops never go outside of any array index and you won't get IndexOutOfRangeException.
EDIT:
var biggestLength1 = Math.Max(array1.Length, array2.Length);
for (int a = 0; a < biggestLength1; a++)
{
var biggestLength2 = 0;
if (array1.Length > a && array2.Length > a)
{
biggestLength2 = Math.Max(array1[a].Length, array2[a].Length);
}
else
{
biggestLength2 = array1.Length > a ? array1.Length : array2.Length;
}
for (int b = 0; b < biggestLength2; b++)
{
if (a < array1.Length &&
a < array2.Length &&
b < array1[a].Length &&
b < array2[a].Length)
{
// every array has enough elements count
// you can do operations with both arrays
}
else
{
// some array is bigger
}
}
}

check if array is chronological

I have a list of integer arrays, and i want to check for each array if the array if chronological, if it is not I want it to be removed from the list.
At the moment I do it like this:
for (int i = 0; i < allXcombis.Count(); i++)
{
bool remove = false;
for (int j = 0; j < allXcombis[i].Length; j++)
{
if (allXcombis[i].Count() - 1 > j)
if (allXcombis[i][j] != allXcombis[i][j + 1] - 1)
remove = true;
}
if (remove)
allXcombis.Remove(allXcombis[i]);
}
but I am not really happy with this code, I think it can be done easier.
First, I would probably extract the checking that the array is “chronological” into its own method and made it more efficient, by returning from the loop early:
bool IsChronological(int[] array)
{
for (int i = 0; i < array.Length - 1; i++)
{
if (array[i] != array[i + 1] - 1)
return false;
}
return true;
}
And then I would simply use RemoveAll():
allXcombis.RemoveAll(a => !IsChronological(a));
This way, you get concise, readable code and you don't have to worry about indexes in the list (as others mentioned, you have a bug in your code, because you're not careful about the indexes).
When you are removing from list inside loop, you need either to fix loop variable or to loop backwards. Then, you don't need () after Count. And you can break from loop after assigning remove = true, this will improve performance.
for (int i = allXcombis.Count - 1; i >= 0; i--)
{
bool remove = false;
for (int j = 0; j < allXcombis[i].Length; j++)
{
if (allXcombis[i].Length - 1 > j)
{
if (allXcombis[i][j] != allXcombis[i][j + 1] - 1)
{
remove = true;
break;
}
}
}
if (remove)
allXcombis.Remove(allXcombis[i]);
}
If by chronological you mean sorted, then you need to check < not !=.
Also you can simplify some things. The most important is when you find that it's not sorted to break out of the inner loop, so that you don't keep iterating.
Also you need to decrease i when you remove, because you'll skip some arrays otherwise (say if i = 2 and you remove the second array, then the third array becomes second, but i will be 3 on the next iteration, so you'll skip it)
for (int i = 0; i < allXcombis.Count; i++)
{
for (int j = 0; j < allXcombis[i].Length-1; j++)
{
if (allXcombis[i][j] > allXcombis[i][j + 1] - 1)
{
allXcombis.Remove(allXcombis[i]);
i--;
break;
}
}
}
I agree with svick in the use of a dedicated method like he proposed "IsChronological" but I would like to add a little bit of security and performance to this method:
bool IsChronological(int[] array)
{
bool result = ((array == null) || (array.Length == 0)) ? false : true; //Null or empty arrays are not chronological by definition (also avoid exceptions)
if (result)
{
result = (array.Length == 1) ? true : false; //Arrays with only one element are chronological by definition
if (!result)
{
int length = array.Length - 1;
int index = 0;
while ((index < length) && (array[index] == array[index] + 1))
index++;
result = (index == array.length);
}
}
return result;
}

find diagonal in 2 dimensional array

I have a 2-dimensional array with user-entered values. I need to find sum of the even elements in the diagonal of the array.
I know how to declare the array and get it filled by the user, but I'm not sure what even elements in the main diagonal really means.
I know I can find out if a number is even by saying:
if n / 2 == 0
Once I've reported the sum of the even elements in the diagonal, I would like to replace all 0 values in the array with ones.
Diagonal means all places where x and y cordinates are the same
Do if your array contains:
1 3 8 5
3 3 9 7
4 4 5 7
5 1 7 4
Then the diagonal are in bold.
Assuming the array is a square:
int sum = 0;
for(int i = 0; i < numOfArrayRows; i++)
{
//Use the mod operator to find if the value is even.
if(array[i][i] % 2 == 0)
sum += array[i][i];
//Change 0's to ones
for(int j = 0; j < numOfArrayCols; j++)
if(array[i][j] == 0)
array[i][j] = 1;
}
Also, next time add the "Homework" tag if you have a homework question :P
With a two-dimensional array it's really easy, since you don't need any index magic:
int a[N][N] = ...;
int sum = 0;
for(int i=0; i<N; ++i)
if(a[i][i] % 2 == 0) //or a[i] & 1, if you like, just check if it's dividable by 2
sum += a[i][i];
This C++ code shouldn't be that different in C or C#, but you should get the point. Likewise the second question would be as simple as:
int a[M][N] = ...;
for(i=0; i<M; ++i)
for(j=0; j<N; ++j)
if(a[i][j] == 0)
a[i][j] = 1;
And I suspec that the main diagonal is the one that begins with coordinates 0,0.
To replace 0 elements with 1 you would do something like:
if (array[i,j] == 0) array[i,j] == 1;
This sounds like homework - however I will help out :)
So if you have an 2D array, and in order to find the sum of the diagonal values, you will know that the indices of both of the values would match in order to provide you with each of the diagonal values.
To iterate through these you could use a simple loop that would sum up every diagonal value, as shown:
//Your Sum
int sum = 0;
//This will iterate and grab all of the diagonals
//You don't need to iterate through every element as you only need
//the diagonals.
for(int i = 0; i < sizeOfArray; i++)
{
//This will add the value of the first, second, ... diagonal value to your sum
sum += array[i,i];
}
To set each of the values that is 0 to 1, you could iterate through each element of the array and check if the value is 0, then set that value to 1, for example:
for(int i = 0; i < sizeOfArray; i++)
{
for(int j = 0; j < sizeOfArray; j++)
{
//Check if this value is 0;
//If it is 0, set it to 1, otherwise continue
}
}
int[,] array = new int[,] {{1,2,3},
{4,5,6},
{7,8,9}};
//Suppose you want to find 2,5,8
for(int row = 0; row < 3; row++)
{
for(int column = 0; column < 3; column++)
{
if((row == 0 && column == 1) || (row == 1 && column == 1) || (row == 2 && column == 1))
{
Console.WriteLine("Row: {0} Column: {1} Value: {2}",row + 1, column + 1, array[row, column]);
}
}
}
Here is the code you need, not much explain:
//Read the size of the array, you can get it from .Count() if you wish
int n = Convert.ToInt32(Console.ReadLine());
int[][] a = new int[n][];
//Reading all the values and preparing the array (a)
for (int a_i = 0; a_i < n; a_i++)
{
string[] a_temp = Console.ReadLine().Split(' ');
a[a_i] = Array.ConvertAll(a_temp, Int32.Parse);
}
//performing the operation (google what diagonal matrix means)
int PrimarySum = 0, SecondarySum = 0;
for (int i = 0; i < n; i++)
{
//The If condition is to skip the odd numbers
if (a[i][i] % 2 == 0) { PrimarySum += a[i][i]; }
//For the reverse order
int lastelement = a[i].Count() - 1 - i;
if (a[i][lastelement] % 2 == 0) { SecondarySum += a[i][lastelement]; }
}
//Get the absolute value
Console.WriteLine(Math.Abs(PrimarySum - SecondarySum).ToString());
Console.ReadKey();

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