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.
Related
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
Lets say i have an array with 10 elements in it. I want to compare the first number is it the biggest in that same array.
Is there any way to make it without linq.
Numbers are 2 4 6 7 8 9 3
I want to know if the first number is biggest or equal in array
I agree with Ethan...
but to answer your question..
(not tested and not compiled => out of the head :))
var first = numbers[0];
foreach (var number in numbers)
{
if (number > first)
return false;
}
return true;
You should iterate over the array and check if there is at least one element that is bigger then the first element.
var array = new [] { 2, 4, 6, 7, 8, 9, 3 };
int element = array[0];
bool isBiggestOrEqual = true;
for (int i = 1; i < array.Length; i++)
{
if (element < array[i])
{
isBiggestOrEqual = false;
break;
}
}
Console.WriteLine("Is {0} the biggest or equal to biggest in array ? {1}", element, isBiggestOrEqual);
you can use the following
public static bool IsFirstAMax(int[] array)
{
if (array.Length == 0)
return false;
if(array.Length ==1)
return true;
var max = array[0];
for(var index = 1; index < array.Length;index++)
if(array[index]>max)
return false;
return true;
}
here a working demo
you need to loop through each number in your array , return true or false depending if your first number is the bigger in the array :
bool CheckFirstNumber(int[] iArray)
{
bool bResult = true;
int FirstNumber = iArray[0];
for (int i = 1;i < iArray.Count() ;i++)
{
if (FirstNumber < iArray[i])
bResult = false;
break;
}
return bResult;
}
or just use link in one line of code
return iArray.Max() == iArray.First() ? true : false
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];
}
What I'm trying to do is simple but it's just slooow. Basically I'm looping through data (byte array), converting some parts to a INT and then comparing it to RamCache with is also a byte array. The reason why I'm converting it to a INT is because it's 4 bytes so if 4 bytes are equal in some part of the RamCache array I know it's already 4 length equal.
And then from there I can see how many bytes are equal.
In short what this code must do:
Loop through the data array and take 4 bytes ,then look if it contains in the RamCache array. Currently the code below is slow when the data array and RamCache array contains 65535 bytes.
private unsafe SmartCacheInfo[] FindInCache(byte[] data, Action<SmartCacheInfo> callback)
{
List<SmartCacheInfo> ret = new List<SmartCacheInfo>();
fixed (byte* x = &(data[0]), XcachePtr = &(RamCache[0]))
{
Int32 Loops = data.Length >> 2;
int* cachePtr = (int*)XcachePtr;
int* dataPtr = (int*)x;
if (IndexWritten == 0)
return new SmartCacheInfo[0];
//this part is just horrible slow
for (int i = 0; i < data.Length; i++)
{
if (((data.Length - i) >> 2) == 0)
break;
int index = -1;
dataPtr = (int*)(x + i);
//get the index, alot faster then List.IndexOf
for (int j = 0; ; j++)
{
if (((IndexWritten - j) >> 2) == 0)
break;
if (dataPtr[0] == ((int*)(XcachePtr + j))[0])
{
index = j;
break;
}
}
if (index == -1)
{
//int not found, lets see how
SmartCacheInfo inf = new SmartCacheInfo(-1, i, 4, false);
inf.instruction = Instruction.NEWDATA;
i += inf.Length - 1; //-1... loop does +1
callback(inf);
}
else
{
SmartCacheInfo inf = new SmartCacheInfo(index, i, 0, true); //0 index for now just see what the length is of the MemCmp
inf.Length = MemCmp(data, i, RamCache, index);
ret.Add(inf);
i += inf.Length - 1; //-1... loop does +1
}
}
}
return ret.ToArray();
}
Double looping is what's making it so slow. The data array contains 65535 bytes and so goes for the RamCache array. This code is btw some part of the Cache system I'm working at it's for my SSP project.
Sort the RamCache array or a copy of the array and use a Array.BinarySearch. If you cannot sort it, create a HashSet of the RamCache.
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;