How to calculate distance between two values from two different 2d array - c#

I have two bool[5,5] arrays which look like this:
1st:
1 1 1 1 1
0 1 0 0 0
0 0 1 1 0
0 0 0 0 0
0 1 0 1 0
2nd:
0 0 0 0 1
0 1 1 1 0
0 0 0 0 0
0 0 1 1 0
1 0 0 0 0
What I have to do is simple calculating distance between 1 from 1st array and 1 from the 2nd one. I had multiple tries to solve this problem, but I can't solve this.
The result should looks like this:
4+3+2+1+0
0+0+0+0+0
0+0+0+0+0
0+0+0+0+0
0+1+0+3+0
Let me name arrays: first[,] and second[,]
There are fiew conditions:
if (first[i,j] == true && second[i,j] == true) distance[i,j] = 0
if (first[i,j] == false) distance[i,j] = 0
if (first[i,j] == true) then I have to calculate distance between closest 1 from second[,] eg. There are 1 in first[1,4] and first[3,4] and there is 1 in second[0,4] (there was mistake), so it means that distance[3,4] = 3 - 0 (because of second array's dimensions).
This is main method to calculate:
` static public int findPicture()
{
int[,] m = new int[testBitmap.GetLength(0),
testBitmap.GetLength(1)];
foreach (var picture in pictures)
{
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (testBitmap[i,j] == true)
{
do
{
i = i + 1;
} while (picture.Value[i,j] != true);
m[i,j] += 1;
}
}
}
var total = 0;
for (int a = 0; a < 5; a++)
{
for (int b = 0; b < 5; b++)
{
total += m[a, b];
}
}
return total;
}
return -1;
}`
It was my closest version to solve.
I would be very greatful if you could give some advices to solve this trivial problem.

I'd do something like this:
static int[,] BuildDistanceArray(bool[,] array1, bool[,] array2)
{
if (array1.GetLength(0) != array2.GetLength(0) || array1.GetLength(1) != array2.GetLength(1))
throw new Exception("Array sizes must match.");
int[,] distance = new int[array1.GetLength(0), array1.GetLength(1)];
for (int i = 0; i < array1.GetLength(0); ++i)
{
for (int j = 0; j < array1.GetLength(1); ++j)
{
distance[i, j] = array1[i, j] ? GetDistance(array2, i, j) : 0;
}
}
return distance;
}
static int GetDistance(bool[,] array, int row, int column)
{
int maxColumn = array.GetLength(1);
int distance = 0;
bool again;
do
{
again = false;
if (column - distance >= 0)
{
if (array[row, column - distance])
return distance;
again = true;
}
if (column + distance < maxColumn)
{
if (array[row, column + distance])
return distance;
again = true;
}
distance++;
} while (again);
return 0;
}
It gives the results you're looking for and it works for any size array.

This function calculates distance between 2 rows converted to int32. It's written in java, so some minor transformation will be required.
int distance(int x, int y) {
int count = Integer.bitCount(x);
int totalDist = 0;
for (int offset = 0; offset < 5 && x != 0; offset++) {
x = x ^ (x & (y << offset) & 0b11111);
x = x ^ (x & (y >>> offset));
int nextCount = Integer.bitCount(x);
totalDist += (count - nextCount) * offset;
count = nextCount;
}
return totalDist;
}

Related

Insert elements into an array in sorted order

What I would like to do is as I take input from user, insert that input into the array in a sorted order, eg. user inputs 22,3,9,10,33
output would be: 3,9,10,22,33.
The code I have below is working except for the fact that for the last element being added is at the wrong index. This was a test for school(which is why the array is 50 elements big and theres a whole class with getters and setters & lack of error checking) and I'm trying to see where I'm going wrong, I've tried both insertion and selection sort which both produce this result. From my understanding, it should be forty five consecutive zeros and then my elements in ascending order.
eg) This is the output I get(wether i use selection or insertion sort after calling my print method
Sorted Array: 0 0 0 0 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 9 10 22
public class test
{
private int [] arr;
private int maxSize;
private int numItems;
public test(int maxSize)
{
this.maxSize = maxSize;
numItems = 0;
arr = new int[maxSize];
}
public bool addItem(int key)
{
if (numItems < maxSize)
{
selectionSort(key);
arr[numItems] = key;
numItems++;
return true;
}
return false;
}
public bool insertionSort(int key)
{
int n = arr.Length - 1;
for (int i = 1; i < n; i++)
{
key = arr[i];
int j = i - 1;
while(j>=0 && arr[j] > key)
{
arr[j+1] = arr[j];
j --;
}
arr[j + 1] = key;
}
return true;
}
public bool selectionSort(int key)
{
int n = arr.Length - 1;
for (int i = 0; i < n; i++)
{
key = i;
for(int j = i + 1; j < n; j++)
{
if (arr[j] < arr[key])
{
key = j;
}
}
int temp = arr[key];
arr[key] = arr[i];
arr[i] = temp;
}
return true;
}
static void Main(string[] args)
{
test x = new test(50);
int count = 0;
int element;
while (count < 5)
{
Console.WriteLine("Enter an element to add into the array");
element = Convert.ToInt32(Console.ReadLine());
x.addItem(element);
count++;
}}
I found two issues with your code and these were minor.
Update addItem function to move selectionSort below the assignment operation.
public bool addItem(int key)
{
if (numItems < maxSize)
{
arr[numItems] = key;
selectionSort(key); // below the arr[numItems] assignment.
numItems++;
return true;
}
return false;
}
and in the selectionSort method, change two things.
a. for loop for j should go all the way to n and
b. break when k=j;
public bool selectionSort(int key)
{
int n = arr.Length - 1;
for (int i = 0; i < n; i++)
{
key = i;
for (int j = i + 1; j <= n; j++) // <= n instead of < n
{
if (arr[j] < arr[key])
{
key = j;
break; // break here once you have k = j.
}
}
int temp = arr[key];
arr[key] = arr[i];
arr[i] = temp;
}
return true;
}
This should take care of your issues.
i think you are looking for insertion sort here is an example.
static void Main(string[] args)
{
int[] numbers = new int[10] {22,1,34,20,12,10,5,33,11,5};
Console.WriteLine("\nOriginal Array Elements :");
Show(numbers);
Console.WriteLine("\nSorted Array Elements :");
Show(InsertionSort(numbers));
Console.ReadKey();
}
static int[] InsertionSort(int[] inputArray)
{
for (int i = 0; i < inputArray.Length - 1; i++)
{
for (int j = i + 1; j > 0; j--)
{
if (inputArray[j - 1] > inputArray[j])
{
int temp = inputArray[j - 1];
inputArray[j - 1] = inputArray[j];
inputArray[j] = temp;
}
}
}
return inputArray;
}
public static void Show(int[] array)
{
foreach (int i in array)
{
Console.Write(i.ToString() + " ");
}
}

Fall down elements in 2d array

Hello looking for simple loop where numbers will fall down in 2d array for example
0 0 0 3 3
2 1 3 1 1
1 1 5 1 1
1 2 0 0 0
0 0 0 0 2
expected:
0 0 0 0 0
0 0 0 0 3
2 1 0 3 1
1 1 3 1 1
1 2 5 1 2
Do you have suggestions? Thank you.
Hint: Fall down means non-zero items must go down in each column!
Here is a solution:
void FallDown(ref int[,] numbers)
{
var rowCount = numbers.GetLength(0);
for (var c = 0; c < numbers.GetLength(1); c++)
{
var colValues = new List<int>();
for (var r = 0; r < rowCount; r++)
{
var colValue = numbers[r, c];
if (colValue > 0)
{
colValues.Add(colValue); // collect only non-zero values
}
}
if (colValues.Count < rowCount) // there were zeroes ...
{
do
{
colValues.Insert(0, 0); // fill it up with leading zeroes.
} while (colValues.Count < rowCount);
for (var r = 0; r < rowCount; r++) {
numbers[r, c] = colValues[r]; // put numbers back into original array
}
}
}
}
The result will be replaced in the original array, which is why it is passed in by ref.
Found this.
public void FallDown()
{
for (var row = 0; row < RowCount - 1; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
if (tiles[row + 1, column] == 0 && tiles[row, column] != 0)
{
tiles[row + 1, column] = tiles[row, column];
tiles[row, column] = 0;
row = 0;
column = 0;
}
}
}
}

C# updating values in two dimensional array

I'm converting an Eight Queens solution from Java to C# just to get my head around C# a bit more. The problem is that I'm stuck with changing values on the board. I can change the value inside the function but it goes back to what it was immediately even when I'm using ref. At the moment I'm using a global variable rather than passing the board as an argument.
Here is the code:
public static int[,] solution;
static void Main()
{
int n = 8;
solution = new int[8,8];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
solution[i,j] = 0;
}
}
Solve(n);
Console.ReadKey();
}
public static void Solve(int n)
{
if (placeQueens(0, n))
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(" " + solution[i,j]);
}
Console.WriteLine();
}
}
else
{
Console.WriteLine("No possible solution");
}
}
public static bool placeQueens(int queen, int n)
{
if (queen == n)
{
return true;
}
for (int row = 0; row < n; row++)
{
if (canPlace(row, queen))
{
solution[row,queen] = 1;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(" " + solution[i, j]);
}
Console.WriteLine();
}
//When I print the current board here the 1 is set
//When placeQueens is called again it is back to being 0
if (placeQueens(queen + 1, n))
{
return true;
}
solution[row,queen] = 0;
}
}
return false;
}
public static bool canPlace(int row, int col)
{ //Just checks that the position is legal}
What can I do to make the 1 stay as a one once I've changed it in placeQueen?
I changed the static variable to being passed in each method instead of being a static variable, and it works perfectly:
static void Main()
{
int n = 8;
var solution = new int[8, 8];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
solution[i, j] = 0;
}
}
Solve(solution, n);
}
public static void Solve(int[,] solution, int n)
{
if (placeQueens(solution, 0, n))
{
Console.WriteLine();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(" " + solution[i, j]);
}
Console.WriteLine();
}
}
else
{
Console.WriteLine("No possible solution");
}
}
public static bool placeQueens(int[,] solution, int queen, int n)
{
if (queen == n)
{
return true;
}
for (int row = 0; row < n; row++)
{
if (canPlace(solution, row, queen))
{
solution[row, queen] = 1;
Console.WriteLine();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
Console.Write(" " + solution[i, j]);
}
Console.WriteLine();
}
if (placeQueens(solution, queen + 1, n))
{
return true;
}
solution[row, queen] = 0;
}
}
return false;
}
public static bool canPlace(int[,] solution, int row, int col)
{
for (var dx = -1; dx <= 1; dx++)
{
for (var dy = -1; dy <= 1; dy++)
{
if (dx == 0 && dy == 0)
continue;
int r = row, c = col;
while (r >= 0 && r <= solution.GetUpperBound(0) && c >= 0 && c <= solution.GetUpperBound(1))
{
if (solution[r, c] == 1)
return false;
r += dy;
c += dx;
}
}
}
return true;
}
The last line it outputs is a correct solution:
1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0
0 0 1 0 0 0 0 0

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);
}
}

Transferring data from textbox to 2D Array

I have a problem with my C# project.
Suppose I have a textbox1 as follow (n rows x n columns):
0 1 0 1 0 1 0 1
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0
Now I want to transfer data from this text box into an existed 2d Matrix that will store data in Integer Type.
I tried this but it seem to not works:
private void GETNUMERICDATA()
{
string txt = textbox1.text;
txt = txt.Replace(" ", string.Empty);
for (int k = 0; k < 32; k++)
{
for (int l = 0; l < 32; l++)
{
for (int i = 0; i < txt.Length; i++)
{
char chr = txt[i];
if (chr == '0')
{
Matrix[k, l] = (int)char.GetNumericValue('0');
}
else
{
if (chr == '1')
Matrix[k, l] = (int)char.GetNumericValue('1');
}
}
}
}
}
How do I do it?
The problem is the third loop over the input. You loop through the whole input every time. The result is, that after all loops have finished, the array will contain only the last value of your input. Try this:
private void GETNUMERICDATA()
{
int currentPosition = 0;
string txt = textbox1.text;
txt = txt.Replace(" ", string.Empty);
for (int k = 0; k < 32 && currentPosition < txt.Length; k++)
{
for (int l = 0; l < 32 && currentPosition < txt.Length; l++)
{
char chr = txt[currentPosition];
if (chr == '0')
{
Matrix[k, l] = (int)char.GetNumericValue('0');
}
else if (chr == '1')
{
Matrix[k, l] = (int)char.GetNumericValue('1');
}
currentPosition++;
}
}
}
It's solved. Just modify in txt;
private void GETNUMERICDATA()
{
int currentPosition = 0;
string txt = textbox1.text;
txt = txt.Replace(" ", string.Empty);
txt = txt.Replace(Environment.Newline, string.Empty);
//Just add this code line
for (int k = 0; k < 32 && currentPosition < txt.Length; k++)
{
for (int l = 0; l < 32 && currentPosition < txt.Length; l++)
{
char chr = txt[currentPosition];
if (chr == '0')
{
Matrix[k, l] = 0;
}
else if (chr == '1')
{
Matrix[k, l] = 1;
}
currentPosition++;
}
}
}
Thanks all for your helping! Have a nice day.

Categories