Related
I'm trying to use the Span2D type to "roll" entries in a 2d array, but it's not working as expected.
By rolling I mean the following - given an array such as:
{
{ 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2 },
{ 0, 0, 0, 0, 0 },
}
I would like to copy the first two rows down one row, so the top row can be repopulated. After the roll operation the array should look like this:
{
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2 },
}
The Span2d CopyTo method seems perfect for this - I create a Slice of the top two rows, and a slice of the bottom two rows, copy the first slice to the second slice. But instead of the expected result above, I get:
{
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
}
Here's a runnable class that shows the problem:
public class SpanTest
{
public static void Main()
{
int[,] array =
{
{ 1, 2, 3, 4, 5 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
};
var h = array.GetLength(0) - 1;
var w = array.GetLength(1);
Console.WriteLine($"slice height:{h} width: {w}\n-----------");
Span2D<int> span = array;
Console.WriteLine($"{span.ToStringMatrix()}-----------");
var sourceSlice = span.Slice(0, 0, h, w);
Console.WriteLine($"{sourceSlice.ToStringMatrix()}-----------");
var targetSlice = span.Slice(1, 0, h, w);
Console.WriteLine($"{targetSlice.ToStringMatrix()}-----------");
sourceSlice.CopyTo(targetSlice);
Console.WriteLine($"{span.ToStringMatrix()}-----------");
}
}
with a helper for printing the Span2Ds:
public static class Utils
{
public static string ToStringMatrix<T>(this Span2D<T> arr)
{
var sb = new StringBuilder();
for (var i = 0; i < arr.Height; i++)
{
for (var j = 0; j < arr.Width; j++)
{
sb.Append($"{arr[i, j]} ");
}
sb.Append(Environment.NewLine);
}
return sb.ToString();
}
}
How can I make the copy operation behave as expected? Thanks
Well, the answer is quite obvious actually - at least it was when it occurred to me at 5am this morning!
Span2D wraps an array, copying to itself alters the backing array during the copy process. By the time the second row is copied, it already contains the contents of the first row. And hence, the first row gets propagated throughout the 2d array.
I have a "Contact" object which contains a list called "Linked" containing the "Contact" linked to it.
public class Contact
{
public int Id { get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public List<Contact> Linked { get; set; }
}
For example, Contact "A" has 3 linked contacts: B, C and D.
As the links are made in both directions each time, B, C and D all have A in their "Linked" contacts.
B can then have E as a contact, and so on. There is no limit.
I have to make an algo which takes a starting contact and an ending contact as a parameter and which finds the shortest path that links them.
The result must be in the form: A > B > F > H > X, if I have to find the path that goes from A to X. We must therefore find all the steps of the path in the result.
I've tried a lot of stuff (recursion, ...) but it's still getting stuck somewhere.
Do you have an idea?
Dijkstra's algorithm is probably what you are looking for.
http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
Dijkstra's algorithm (/ˈdaɪkstrəz/ DYKE-strəz) is an algorithm for finding the shortest paths between nodes in a graph, which may represent, for example, road networks. It was conceived by computer scientist Edsger W. Dijkstra in 1956 and published three years later.[4][5][6]
It should be relatively straight forward to find examples in your given language. Here is one in C#, stolen from programmingalgorithms.com
private static int MinimumDistance(int[] distance, bool[] shortestPathTreeSet, int verticesCount)
{
int min = int.MaxValue;
int minIndex = 0;
for (int v = 0; v < verticesCount; ++v)
{
if (shortestPathTreeSet[v] == false && distance[v] <= min)
{
min = distance[v];
minIndex = v;
}
}
return minIndex;
}
private static void Print(int[] distance, int verticesCount)
{
Console.WriteLine("Vertex Distance from source");
for (int i = 0; i < verticesCount; ++i)
Console.WriteLine("{0}\t {1}", i, distance[i]);
}
public static void Dijkstra(int[,] graph, int source, int verticesCount)
{
int[] distance = new int[verticesCount];
bool[] shortestPathTreeSet = new bool[verticesCount];
for (int i = 0; i < verticesCount; ++i)
{
distance[i] = int.MaxValue;
shortestPathTreeSet[i] = false;
}
distance[source] = 0;
for (int count = 0; count < verticesCount - 1; ++count)
{
int u = MinimumDistance(distance, shortestPathTreeSet, verticesCount);
shortestPathTreeSet[u] = true;
for (int v = 0; v < verticesCount; ++v)
if (!shortestPathTreeSet[v] && Convert.ToBoolean(graph[u, v]) && distance[u] != int.MaxValue && distance[u] + graph[u, v] < distance[v])
distance[v] = distance[u] + graph[u, v];
}
Print(distance, verticesCount);
}
It would then be used like so:
int[,] graph = {
{ 0, 4, 0, 0, 0, 0, 0, 8, 0 },
{ 4, 0, 8, 0, 0, 0, 0, 11, 0 },
{ 0, 8, 0, 7, 0, 4, 0, 0, 2 },
{ 0, 0, 7, 0, 9, 14, 0, 0, 0 },
{ 0, 0, 0, 9, 0, 10, 0, 0, 0 },
{ 0, 0, 4, 0, 10, 0, 2, 0, 0 },
{ 0, 0, 0, 14, 0, 2, 0, 1, 6 },
{ 8, 11, 0, 0, 0, 0, 1, 0, 7 },
{ 0, 0, 2, 0, 0, 0, 6, 7, 0 }
};
Dijkstra(graph, 0, 9);
The example above consist of 9 nodes, and the distance to each of the other nodes. If it has 0, there is no connection. In your case, there is no weight - so either there is a connection (1), or there isn't (0).
You have to change the algorithm to take in a list of contacts, instead of a two dimensional array. Try to think of the two dimensional array as a list of lists - very similar to a list of contacts, where each contact has another list of contacts.
Lets for example create a simple contacts list and their contacts:
Peter can contact Mary
Mary can contact Peter and John
John can contact Mary
This would be represented something like this in a two dimensional array:
int[,] contacts = new int[]
{
{ 0, 1, 0 }, //Peter: Peter no, Mary yes, John no
{ 1, 0, 1 }, //Mary: Peter yes, Mary no, John yes
{ 0, 1, 0 } //John: Peter no, Mary yes, John no
}
You would also have to modify the algorithm to keep track of the current path. That should be a relatively straight forward change.
Hope that it helps!
I have been facing this line of code in a book(JAVA) many times.
It seems like it sets matrix with hardcoded values.
Mat src = new Mat(4, 1, CvType.CV_32FC2);
src.put(0, 0,
0, 0,
img.width() - 1, 0,
0, img.height() - 1,
img.width() - 1, img.height() - 1
);
And couldn't find what is equivalent to .put method in C#.
I have latest 4 version.
put method inserts data at starting position specified by row and column.
public int put(int row, int col, int[] data)
Equivalent in OpenCVSharp is
Mat src = new Mat(4, 1, MatType.CV_32FC2,
new []
{
0, 0,
img.Width - 1, 0,
0, img.Height - 1,
img.Width - 1, img.Height - 1
});
Documentation
I've taken a 2D array of UInt16 values, and converted it to raw bytes. I would like to take those bytes and convert them back into the original 2D array, but I'm unsure of how to do this when I only have the bytes, i.e., is there a way to determine the dimensions of an original array when all you have is that array converted to bytes?
Here's my code:
UInt16[,] dataArray = new UInt16[,] {
{4, 6, 2},
{0, 2, 0},
{1, 3, 4}
};
long byteCountUInt16Array = dataArray.GetLength(0) * dataArray.GetLength(1) * sizeof(UInt16);
var bufferUInt16 = new byte[byteCountUInt16Array];
Buffer.BlockCopy(dataArray, 0, bufferUInt16, 0, bufferUInt16.Length);
//Here is where I try to convert the values and print them out to see if the values are still the same:
UInt16[] originalUInt16Values = new UInt16[bufferUInt16.Length / 2];
Buffer.BlockCopy(bufferUInt16, 0, originalUInt16Values, 0, BufferUInt16.Length);
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Values---: " + originalUInt16Values[i]);
}
This code will put the bytes into a 1-dimensional array, but I would like to put them into the original 2d array. Is this possible when if all I have are the raw bytes? I'll eventually be sending these bytes via a REST call and the receiving side will only have the bytes to convert back into the original 2D array.
So... not certain exactly what you're specifications are, but you could send the dimensions (x,y) of the array as the first four bytes of your buffer. below is my crack at it. I heavily commented it so hopefully it should make sense there. Ask any questions if that code isn't clear.
/**** SENDER *****/
// ushort and UInt16 are the same (16-bit, 2 bytes)
ushort[,] dataArray = new ushort[,] {
{4, 6, 2},
{0, 2, 0},
{1, 3, 4}
};
// get the X and Y dimensions
ushort xDim = (ushort)dataArray.GetLength(0);
ushort yDim = (ushort)dataArray.GetLength(1);
// Make an array for the entire 2D array and the dimension sizes
ushort[] toSend = new ushort[xDim * yDim + 2];
// load the dimensions into first two spots in the array
toSend[0] = xDim;
toSend[1] = yDim;
// load everything else into the array
int pos = 2;
for (int i = 0; i < xDim; i++)
{
for (int j = 0; j < yDim; j++)
{
toSend[pos] = dataArray[i, j];
pos += 1;
}
}
// size of the array in bytes
long byteCountUInt16Array = sizeof(ushort) * (xDim * yDim + 2);
// create the byte buffer
var bufferUInt16 = new byte[byteCountUInt16Array];
// copy everything (including dimensions) into the byte beffer
Buffer.BlockCopy(toSend, 0, bufferUInt16, 0, bufferUInt16.Length);
/***********RECEIVER************/
// get the dimensions from the received bytes
ushort[] xyDim = new ushort[2];
Buffer.BlockCopy(bufferUInt16, 0, xyDim, 0, sizeof(ushort) * 2);
// create buffer to read the bytes as ushorts into, size it based off of
// dimensions received.
ushort[] readIn = new ushort[xyDim[0] * xyDim[1]];
Buffer.BlockCopy(bufferUInt16, sizeof(ushort) * 2, readIn, 0, sizeof(ushort) * readIn.Length);
// create 2D array to load everything into, size based off of received sizes
ushort[,] originalUInt16Values = new ushort[xyDim[0], xyDim[1]];
// load everything in
int cur = 0;
for (int i = 0; i < xyDim[0]; i++)
{
for (int j = 0; j < xyDim[1]; j++)
{
originalUInt16Values[i, j] = readIn[cur];
cur += 1;
}
}
// print everything out to prove it works
for (int i = 0; i < xyDim[0]; i++)
{
for (int j = 0; j < xyDim[1]; j++)
{
Console.WriteLine("Values at {0},{1}: {2}", i, j, originalUInt16Values[i, j]);
}
}
// uhh... keep the console open
Console.ReadKey();
You can't get the original dimensions. Example:
8 bytes = [0, 1, 0, 2, 0, 1, 0, 2]
into array of 16 bits (2 bytes):
= [1, 2, 1, 2]
into array of 64 bits (4 bytes):
= [65538, 65538]
and all of these ways (1 byte, 2 bytes, 4 bytes) are valid for parsing, so you must indicate your original sizes, or at least one of them. Luckily you may send the sizes (or sizes) in the headers of the request. This may do the trick for what you want.
Another way of doing this is what serial systems do: simply concat your size (or sizes) and your buffer.
size [4 bytes = Int32] + buffer [n bytes]
finally parse the first bytes to read the size and block copy starting from 1 first byte of your buffer (don't forget the offset. In the example above you should start block copying from byte number 5)
I am trying to find the path of a maze, below is the code, it suppose to goes inside the recursiveSolve loop but it keep exiting, after second if condition what i am doing wrong here can someone help me please?
im setting Washere and correctpath array as false by default.
recursiveSolve(0, 0);
public static int[,] maze = {{0, 0, 0, 0, 0, 1},
{1, 1, 0, 0, 0, 1},
{0, 0, 0, 1, 0, 0},
{0, 1, 1, 0, 0, 1},
{0, 1, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 1}};
public static Boolean recursiveSolve(int row, int col) {
Boolean[,] wasHere = new Boolean[6, 6];
Boolean[,] correctPath = new Boolean[6, 6]; // The solution to the maze
if (maze[row, col] == 1 || wasHere[row, col]) {
return false;
}
else if (row == 0 || row == 6 - 1 || col == 0 || col ==6 - 1) {
correctPath[row, col] = true;
return true;
}
else {
wasHere[row, col] = true;
if (recursiveSolve(row - 1, col) || recursiveSolve(row + 1, col) ||
recursiveSolve(row, col - 1) ||
recursiveSolve(row, col +1)) {
correctPath[row, col] = true;
return true; // successfully escaped; this square is on path
}
else {
return false;
}
}
}
Your wasHere and correctPath arrays are local to the recursiveSolve function, which means each time you enter in this function, the arrays will be inited to false (or random value).
First of all try to make these arrays static as well, and see if that solves your problem with the always false.
Also, you should start your search from somewhere inside the maze instead of from an edge (0,0 means you already exiting the maze).
If you want to start from 0,0 ,mark that as a starting point, and don't allow it as a valid solution.
If you're actually doing path finding and this is not an excercise which requires this particular solution, then you might also want to look into the A* algorithm which is probably more efficient and robust.
Wikipedia