Global array in recursive function issue - c#

So i have a globar array and a recursive function. For example, recursive function performs itself 16 times, and bestOrder=array2D line should be reached only twice. Program actually reach it only twice, but bestOrder changes its value every time array2D is changed (array2D[position] = i;) in this line. BestOrder should contain 2 0 3 1 order, but at the end of the function it contains 3 2 1 0 (last value of the array2D). How can i fix that?
private static int[] bestOrder;
private static void Permutate(int[] array2D, int position, Point[] checkpoints)
{
if (position == array2D.Length)
{
if (GetPathLen(checkpoints, array2D) < min)
{
min = GetPathLen(checkpoints, array2D);
bestOrder= array2D;
}
return;
}
for (int i = 0; i < array2D.Length; i++)
{
bool found = false;
for (int j = 0; j < position; j++)
if (array2D[j] == i)
{
found = true;
break;
}
if (found) continue;
array2D[position] = i;
Permutate(array2D, position + 1, checkpoints);
}
}

Arrays are reference type means they are actually not copied when they are assigned to variables or passed to methods. Instead their references are passed (The pointer that points to same location in memory). One way is Clone and cast to actually copy the array.
bestOrder = (int[])array2D.Clone();
Another way is to create empty array. and fill it by elements of another array.
bestOrder = new int[array2D.Length];
for(int i = 0; i < bestOrder.Length; i++)
{
bestOrder[i] = array2D[i];
}

Related

Hello, I am trying to arrange an array from the small value to big value, but its not working

I am trying to arrange an array from the small value to grow, and for some reason this function does not work (SmallToGrow), the rest is excellent. Thanks.
There are auxiliary functions that I use and are excellent facts, only the (SmallToGrow) function does not work for me and I cannot understand why. I'd love anyone who can help. Thanks
enter code here
//this check if all cells equals
public bool EverybodyAreEqual(int [] array)
{
for (int i = 0; i < array.Length - 1; i++)
if (array[i] != array[i + 1])
return false;
return true;
}
//This function changes all the values ​​in the array that contain the -numInArray- value you entered,
// to the -numChanged- value you entered
public void ChangNumWhere(ref int [] array,int numInArray,int numChanged)
{
for (int i = 0; i < array.Length; i++)
if (array[i] == numInArray)
array[i] = numChanged;
}
//A function that returns the number of values ​​that are not equal in the array
public int NumDifferentArray(int [] array)
{
int[] arr = new int[array.Length];
for (int i = 0; i < arr.Length; i++)
arr[i] = array[i];
bool con = true;
int contain = 0;
int index = 0;
for(int i=0; con;i++)
{
if (!arr.Contains(i))
{
contain = i;
con = false;
}
}
while(!this.EverybodyAreEqual(arr))
{
for (int i = 0; i < arr.Length; i++)
if (arr[i] != contain)
{
this.ChangNumWhere(ref arr, arr[i], contain);
index++;
}
}
return index;
}
public int HowTimesExsist(int [] array,int num)
{
int index = 0;
for(int i=0;i<array.Length;i++)
{
if (array[i] == num)
index++;
}
return index;
}
/// This function returns a minimum value as required,
/// for example if you requested 0 the smallest value is returned,
/// if 1 is returned one above it and so on,
/// if the index is greater than the length of the array the largest number is returned
public int MinBottom(int[] array, int num)
{
if (num < 0)
throw new Exception("num canot be less then 0");
int max = this.MaxArray(array);
while (num > 0)
{
int min = this.MinArray(array);
for (int i = 0; i < array.Length; i++)
if(array[i]==min)
array[i] = max;
num--;
}
return this.MinArray(array);
}
public int[] SmallToGrow(int [] array)
{
int i = 0;
int[] arr = new int[array.Length];
for (int j = 0; j < this.NumDifferentArray(array); j++)
for (int b = 0; b < this.HowTimesExsist(array, MinBottom(array, j)); i++, b++)
arr[i] = this.MinBottom(array, j);
return arr;
}
Why don't you use a list instead? They have a method attached to it that sorts it all for you.
List<int> sortInt = new List<int>() { 2, 5, 1, 50, 258, 87, 63, 52, 100, 85, 21 };
sortInt.Sort();
Returned them in numerical order with [0] being 1 and [10] being 258.
you can then turn the list to an array with sortint.ToArray();.
Edit
As dymanoid mentioned you can just use your array and just run the array.Sort() method with it. Learn something new every day.
It looks like you are in large part re-engineering some common functionality in System.Collections.Generic and System.Linq -
public bool EverybodyAreEqual(int[] array)
{
// If all items are the same,
// there should only be one distinct item in the collection
return array.Distinct().Length == 1;
}
public int NumDifferentArray(int[] array)
{
// Group the numbers in the array and
// count the number of groups with only one item
return array.GroupBy(number => number).Where(g => g.Count() == 1);
}
public int HowTimesExsist(int[] array, int num)
{
// Count the number of times a number appears in the array
return array.Count(n => n == num);
}
/// This function returns a minimum value as required,
/// for example if you requested 0 the smallest value is returned,
/// if 1 is returned one above it and so on,
/// if the index is greater than the length of the array the largest number is returned
public int MinBottom(int[] array, int num)
{
if (num < 0)
{
// Be specific about the type of exception you are throwing
throw new ArgumentOutOfRangeException(nameof(num));
}
// Sort a copy of your array
var sorted = Array.Copy(array);
Array.Sort(sorted);
// If there are any items over the specified minimum, return those
// otherwise, return the highest number in the array
// Using LastOrDefault for the maximum will return 0 if the initial array is empty
var itemsOverMinimum = sorted.Where(n => n >= num);
return itemsOverMinimum.Any() ? itemsOverMinimum.First() : sorted.LastOrDefault();
}
public int[] SmallToGrow(int[] array)
{
// Because you are returning an array, that implies that the original array should not change
// Copy the array and sort it
var copy = Array.Copy(array);
Array.Sort(copy);
return copy;
}
I saw that you mentioned that you are trying to find alternative ways to accomplish some of these things, and I want to give you some advice about that.
I think it's pretty cool that you want to challenge yourself. However, this specific functionality is part of System libraries. One of the best parts about working in C# is how much of this sort of thing is already written for you, and this functionality being added to System means that Microsoft believes these pieces are the core (pun intended) building blocks for working in .NET.
Unless your project is to specifically write a better sorting algorithm, you are not going to write this better than it is in those libraries. I've been doing this for a while, and I'm not going to be able to either.
But that doesn't mean you should stop learning. Instead, I would encourage you to look at the github source for the methods I used in my snippets above. I think that will probably be a lot more helpful than re-engineering this stuff from scratch.
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Linq/src/System/Linq/Distinct.cs
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Linq/src/System/Linq/Grouping.cs
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Linq/src/System/Linq/Where.cs
https://github.com/dotnet/runtime/blob/master/src/libraries/System.Linq/src/System/Linq/Count.cs

Any idea why second element of array is not being assigned a value?

I have set up a spreadsheet program with a 26 by 26 grid of cell objects. I set up a method which processes a formula entered by the user. The user can enter, for example, =A1+A2 and the method checks the values of cells A1 and A2 and adds them together. For some reason, the value of the second cell is not being assigned to the array.
https://pasteboard.co/IqRO23M.png
The code continues the switch case statement for other operators but that's not important for this problem.
public static void ProcessBasicFormula(Cell selectedCell,Cell[,]
cell,string[] cellsInUse, char operatorInUse)
{
int[] valueOfCell = new int[cellsInUse.Length]; //valueOfCell and
cellInUse have same length
int counter = 0;
double answer = 0.0;
switch(operatorInUse)
{
case ('+'):
for (int i = 0; i < cellsInUse.Length; i++)
{
for (int j = 0; j < cellsInUse.GetLength(0); j++)
{
for (int k = 0; k < cellsInUse.GetLength(0); k++)
{
if (cellsInUse[i] == cell[j, k].CellID)
{
valueOfCell[counter] =Convert.ToInt32(cell[j,k].Text);
counter++;
}
}
}
}
answer = valueOfCell[0] + valueOfCell[1];
break;
I expect the values of the two cells to be added together but instead, I am getting the first value added by 0.
my assumptions are:
the cellsInUse array length is accurate
List item the cell value at index 1 is not zero
the new int[int] will initialize the array to zeros;
int[] valueOfCell = new int[cellsInUse.Length];
cellsInUse is one dimensional array;
string[] cellsInUse
the getLength(0) of one dimensional array is the same as .length
cellsInUse.length == 2 is true;
cellsInUse.GetLength(0) == 2 is true;
so the j and k loops are looping to 2.
I am assuming the first cell value was lucky enough to be in first subset of [2,2] cells.
should the cellsInUse.GetLength(0) be cell.GetLength(0) => j and cell.GetLength(1) => k

C# find 2D small array in 2d big array

int[,] data = new int[,] {
{ 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0 },
{ 0, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
};
int[,] find = new int[,] {
{ 0, 1 },
{ 1, 1 }
};
bool result = Check2DArray (data, find);
How do I search for a small 2D array in a large 2D array?
You can try this snippet :
static bool Check2DArray(int[,] data, int[,] find)
{
int dataLen = data.Length; // length of the whole data
int findLen = find.Length; // length of the whole find
for(int i = 0; i < dataLen; i++) // iterate through data
{
int dataX = i % data.GetLength(0); // get current column index
int dataY = i / data.GetLength(0); // get current row index
bool okay = true; // declare result placeholder for that check
for (int j = 0; j < findLen && okay; j++) // iterate through find
{
int findX = j % find.GetLength(1); // current column in find
int findY = j / find.GetLength(1); // current row in find
int checkedX = findX + dataX; // column index in data to check
int checkedY = findY + dataY; // row index in data to check
// check if checked index is not going outside of the data boundries
if ( checkedX >= data.GetLength(0) || checkedY >= data.GetLength(1))
{
// we are outside of the data boundries
// set flag to false and break checks for this data row and column
okay = false;
break;
}
// we are still inside of the data boundries so check if values matches
okay = data[dataY + findY, dataX + findX] == find[findY, findX]; // check if it matches
}
if(okay) // if all values from both fragments are equal
return true; // return true
}
return false;
}
You can check that online here
Please give me some feedback and if it is not clear enough I can explain in more details :)
EDIT :
Found an issue that this method was not checking last row and column in the data argument. Now after small fix all works perfectly.
EDIT2 :
Thanks to #SefaTunçkanat for pointing out my mistake. There was an issue with some calculations which could lead to IndexOutOfRange exceptions and comparing wrong inputs. Now everything works fine.
Make a helper method that checks if a big array contains a small array starting at the given position (row, col). Make two nested loops to iterate over all (row, col) pairs in the big array where the small array could fit, and see if any pair would produce a match.
static bool EqualAtPosition(int[,] big, int[,] small, int row, int col) {
var rowCount = small.GetLength(0);
var colCount = small.GetLength(1);
if (row+rowCount > big.GetLength(0) || col+colCount > big.GetLength(1)) {
return false;
}
for (var r = 0 ; r != rowCount ; r++) {
for (var c = 0 ; c != colCount ; c++) {
if (big[row+r, col+c] != small[r, c]) {
return false;
}
}
}
return true;
}
Basically you just loop through all "start" positions that the smaller array could fit in the bigger one, then loop through the values of the smaller array and compare to the relative position in the bigger, if there isn't a match you need to continue to the next position in the bigger array, or if all match you can return true, if you finish going through the bigger array without finding a match then you return false.
public static bool Check2DArray(int[,] data, int[,] find)
{
for (int dRow = 0; dRow < data.GetLength(0) - find.GetLength(0); dRow++)
{
for (int dCol = 0; dCol < data.GetLength(1) - find.GetLength(1); dCol++)
{
bool found = true;
for (int fRow = 0; fRow < find.GetLength(0); fRow++)
{
for (int fCol = 0; fCol < find.GetLength(1); fCol++)
{
if (data[dRow + fRow, dCol + fCol] != find[fRow,fCol])
{
found = false;
break;
}
}
if (!found) break;
}
if (found) return true;
}
}
return false;
}
Also you could use #dasblinkenlight's solution to replace the inner two loops if you want.
Depending on the size of the arrays and your requirements a simple brute-force algorithm may suffice.
You would start at [0,0] in your big array and check if all the items from this coordinate on are equal to the items in the small array.
If they are you have found a match. If not you would go to the next position in the big array.
take the first element of the small array at [0,0] (let's call it start_e)
run with 2 for-loops through the big array
if you find start_e copy the sub array from the big one of the size of the small one and
compare it with a helping method that can check 2 Arrays of same size.

C#: How to add just the values of a 2D array to a dynamically-sized list? [duplicate]

This question already has answers here:
List items changes as I add new data... why?
(6 answers)
Closed 6 years ago.
I need to create a dynamically sized list that contains pairs of points for a window's form using C#. The list size will change depending on the data that is loaded.
A simplified version of my approach, to simply convey the problem, is as follows (in the real app, the for-loops will iterate over sizes dependent on loaded data):
int[,] dummyInt = new int[1, 2];
List<int[,]> test = new List<int[,]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0, 0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[0, 1] = j;
test.Add(dummyInt);
}
}
//Show the values in the list for debugging
foreach (int[,] value in test)
{
MessageBox.Show(value.ToString("G"));
}
Using this approach, all 500 values in the list are [99,4].
What I was expecting/hoping to get was
value 1 [0,0]
value 2 [0,1]
...
value 500 [99,4]
Seems like the list is storing the actual variable, and then changing the value with every iteration of the for loop. How can I store just the value of dummyInt as a new object to the list?
I searched for this, but I'm not sure I know the appropriate vocabulary to nail down the search.
Your List object is storing reference to the dummyInt object. If you want to store different values in List you have to create new int array every time you are adding it to List.
Reference:
https://msdn.microsoft.com/en-gb/library/4d43ts61(v=vs.90).aspx
Firstly, you don't need a 2-dimensional array if you're just storing a pair of coordinates. The first coordinate can go in the first element of a 1-dimensional array, and the second coordinate can go in the second element of the array. Secondly, the Clone method can be used to make a copy of an array object if you want to force a separate copy of the whole array to exist.
int[] dummyInt = new int[2];
List<int[]> test = new List<int[]>();
for (int i = 0; i < 100; i++)
{
dummyInt[0] = i;
for (int j = 0; j < 5; j++)
{
dummyInt[1] = j;
test.Add((int[])dummyInt.Clone());
}
}
foreach (int[] value in test)
{
Console.WriteLine("({0},{1})", value[0], value[1]);
}
And finally, an array might not be the best way to store a pair of coordinates. You might want to use a tuple or make your own structure. If you use a Value type (struct) instead of a Reference type (class), you don't need to clone each one.
struct Pair
{
public int x;
public int y;
}
public class Test
{
public static void Main()
{
Pair dummyInt = new Pair();
List<Pair> test = new List<Pair>();
for (int i = 0; i < 100; i++)
{
dummyInt.x = i;
for (int j = 0; j < 5; j++)
{
dummyInt.y = j;
test.Add(dummyInt);
}
}
foreach (Pair value in test)
{
Console.WriteLine("({0},{1})", value.x, value.y);
}
}
}
Note how the result is different if you change the word struct at the beginning to class.

1-Dimensional Array Counting Same Elements

I have a 1-dimensional array that fills up a table of 40 random elements (all the values are either 0 or 1). I want to find the longest consecutive span of values.
For example:
In 111100101 the longest row would be 1111 because it has four consecutive values of 1.
In 011100 the result is 111.
I have no idea how to check upon the "next element" and check if it's a 0 or 1.
Like the first would be 1111 (count 4) but the next would be a 0 value, meaning I have to stop counting.
My idea was placing this value (4) in a other array (example: 111100101), and place the value of the 1's back on zero. And start the process all over again.
To find the largest value I have made another method that checks up the biggest value in the array that keeps track of the count of 0's 1's, this is not the problem.
But I cannot find a way to fill the array tabelLdr up, having all the values of the group of elements of the same kind (being 0 or 1).
In the code below I have 2 if's and of course it will never go into the second if (to check if the next value in the array is != to its current state (being 0 or 1).
public void BerekenDeelrij(byte[] tabel, byte[] tabelLdr)
{
byte LdrNul = 0, Ldréén = 0;
//byte teller = 0;
for (byte i = 0; i < tabel.Length; i++)
{
if (tabel[i] == 0)
{
LdrNul++;
//this 2nd if cleary does not work, but i have no idea how to implend this sort of idea in my program.
if (tabel[i] == 1) //if value != 0 then the total value gets put in the second array tabelLdr,
{
tabelLdr[i] = LdrNul;
LdrNul = 0
}
}
if (tabel[i] == 1)
{
Ldréén++;
if (tabel[i] == 0)
{
tabelLdr[i] = Ldréén;
Ldréén = 0;
}
}
}/*for*/
}
This method should do what you need:
public int LargestSequence(byte[] array) {
byte? last = null;
int count = 0;
int largest = 0;
foreach (byte b in array) {
if (last == b)
++count;
else {
largest = Math.Max(largest, count);
last = b;
count = 1;
}
}
return Math.Max(largest, count);
}
Even while i is the loop counter, it is still just a variable. A valid for statement is for (;;), which is an infinite loop. Notice the for statement increments i, as in i++. The expression i = i + 1 works just as well.
Im unsure if you need the longest "row" of ones or longest row of either 0 or 1. This will work for the latter
var max = 0;
var start = 0;
var current = -1;
var count = 0;
for(int i = 0;i<table.Length;i++)
{
if(current = table[i])
{
count++;
}
else
{
current = table[i];
if(max < count)
{
max = count;
start = i-count;
}
count = 1;
}
}
if(max < count)
{
max = count;
start = i-count;
}
//max is the length of the row starting at start;

Categories

Resources