How to Get Adjacency matrix from a matrix in c# - c#

supposing I have a matrix like
0 -1 0 0
0 0 -1 0
0 0 0 0
0 0 -1 -1
so in this case The matrix represents:
0's are conected and -1 are not
How can I get Adjacency matrix from it?
I know
h[i][j] = 0, if there is no direct link from i to j
(i and j are not neighbors)
h[i][j] = 1, if there is a direct link from i to j
(i and j are neighbors)
so I am doing something like:
Int32[,] original = new int[4, 4]
{
{0, -1, 0, 0},
{0, 0, -1, 0},
{0, 0, 0, 0},
{0, 0, -1, -1}
}
Int32[,] adjacent;
for (int i = 0; i < original.GetLength(0); i++){
for (int j = 0; j < original.GetLength(1); j++) {
//How to know if there is direct link from i to j
//if(){
// adjacent[i,j]=0;
//}else{
// adjacent[i,j]=1;
//}
}
}

The original code has a problem - the matrixes adjacent and original are not usually the same size.
But it's close, in a way.
Code not tested:
int size = original.GetLength(0) * original.GetLength(1);
int[,] adjacent = new int[size, size];
for (int i = 0; i < original.GetLength(0); i++) {
for (int j = 0; j < original.GetLength(1); j++) {
if (original[i, j] == 0) {
// up/down
if (j > 0 && original[i, j - 1] == 0) {
adjacent[remap(i, j), remap(i, j - 1)] = 1;
adjacent[remap(i, j - 1), remap(i, j)] = 1;
}
// left/right
if (i > 0 && original[i - 1, j] == 0) {
adjacent[remap(i, j), remap(i - 1, j)] = 1;
adjacent[remap(i - 1, j), remap(i, j)] = 1;
}
}
}
}
remap maps a 2D point to a "node index". It may need more arguments. It could be something like:
int remap(int i, int j, int width)
{
return width * i + j;
}
There are other possibilities, but this is the simplest.

The adjacency matrix is an n by n matrix for a graph with n nodes (see an example here), as #harold has stated already. So you need to map between the physical (i,j) coordinates of the node in your grid, and the node number which is between 0 and n-1.
Here is some code that is along the right lines. I have looked at the output in the debugger and checking the first couple of rows it looked ok.
class Program
{
static void AddToAdjacencyMatrix(Int32[,] adjacency, Int32[,] original,
Dictionary<Tuple<int, int>, int> coordinate2NodeNum,
Tuple<int, int> fromCoord, int deltaX, int deltaY)
{
Tuple<int, int> toCoord = new Tuple<int, int>(
fromCoord.Item1 + deltaX, fromCoord.Item2 + deltaY);
try { // quick and dirty way of catching out of range coordinates
if (original[toCoord.Item1,toCoord.Item2] == 0) {
int fromNodeNum = coordinate2NodeNum[fromCoord];
int toNodeNum = coordinate2NodeNum[toCoord];
adjacency[fromNodeNum, toNodeNum] = 1;
adjacency[toNodeNum, fromNodeNum] = 1;
}
}
catch {
}
}
static void Main(string[] args)
{
Int32[,] original = new int[4, 4]
{
{0, -1, 0, 0},
{0, 0, -1, 0},
{0, 0, 0, 0},
{0, 0, -1, -1}
};
// Adjacency matrix has column and row headings for each node in graph
// Therefore we need to map between the node number in the adjacency matrix
// (i.e. the column or row heading) and the physical grid coordinates
Dictionary<int, Tuple<int, int>> nodeNum2Coordinate = new Dictionary<int, Tuple<int, int>>();
Dictionary<Tuple<int, int>, int> coordinate2NodeNum = new Dictionary<Tuple<int, int>, int>();
int nodeCount = 0;
for (int i = 0; i < original.GetLength(0); i++){
for (int j = 0; j < original.GetLength(1); j++) {
if (original[i, j] == 0) {
Tuple<int, int> coord = new Tuple<int, int>(i,j);
nodeNum2Coordinate.Add(nodeCount, coord);
coordinate2NodeNum.Add(coord, nodeCount);
nodeCount++;
}
}
}
// Now create the adacency matrix
Int32[,] adjacency = new int[nodeCount, nodeCount];
for (int i = 0; i < original.GetLength(0); i++){
for (int j = 0; j < original.GetLength(1); j++) {
if (original[i, j] == 0) {
Tuple<int, int> fromCoord = new Tuple<int, int>(i,j);
// Check connections
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
-1, 0); // UP
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
+1, 0); // DOWN
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
0, -1); // LEFT
AddToAdjacencyMatrix(adjacency, original, coordinate2NodeNum, fromCoord,
0, +1); // UP
}
}
}
Console.ReadLine();
}
}

Related

Wrong output of Dijkstra algorithm using C#

I tried to implement dijkstra algorithm in c# but the output is wrong and it can not calculate right distance from source node.
I use an array called distance to update and store shortest path from source node.
Vertex list is declared to save intermediate nodes that construct shortest path.
Here is my code :
namespace Dijkstra
{
public class Program
{
static void Main(string[] args)
{
int[][] graph = {
new int []{ 0, 1, 7, 0, 0 },
new int [] { 0, 0, 4,4, 1},
new int []{ 0, 0, 0, 3, 2 },
new int []{ 0, 0, 0, 0, 5 },
new int []{ 0, 0, 0, 0, 0 } };
ShortestPath(graph, 0);
}
static void ShortestPath(int[][]graph,int source)
{
int nodes = graph.GetLength(0);
int[] distance = new int[nodes];
List<int> vertex = new List<int>();
List<int> edge = new List<int>();
int nearvertex = 0;
int min = int.MaxValue;
for(int i = 0; i< graph.GetLength(0); i++)
{
distance[i] = graph[source][i];
if (distance[i] == 0 && i != source)
distance[i] = int.MaxValue;
}
while(nodes-1 > 0)
{
min = int.MaxValue;
for (int j = 0; j < graph.GetLength(0); j++)
{
if (distance[j] <= min && 0 < distance[j] && !vertex.Contains(j))
{
min = distance[j];
nearvertex = j;
}
}
edge.Add(min);
for (int i = 0; i < graph.GetLength(0); i++)
{
if (distance[nearvertex] + graph[nearvertex][i] < distance[i] &&!vertex.Contains(i))
{
distance[i] = distance[nearvertex] + graph[nearvertex][i];
vertex.Add(nearvertex);
}
}
distance[nearvertex] = -1;
nodes--;
}
foreach(var i in edge)
Console.WriteLine(i);
}
}
}
Is there any problem with comparisons in for loops?
How can i fix it?
There are few things wrong on your code. I'll point them for you.
See below code and comments.
static void ShortestPath(int[][] graph, int source)
{
int nodes = graph.GetLength(0);
int[] distance = new int[nodes];
List<int> vertex = new List<int>();
int nearvertex = 0;
int min = int.MaxValue;
for (int i = 0; i < distance.Length; i++)
{
// Distance array should be initialized to max except source vertex.
distance[i] = int.MaxValue;
}
distance[source] = 0;
while (nodes - 1 > 0)
{
min = int.MaxValue;
for (int j = 0; j < graph.GetLength(0); j++)
{
// 0 < distance[j] --> 0 <= distance[j] : starting point distance is 0, so should be <=
if (distance[j] <= min && 0 <= distance[j] && !vertex.Contains(j))
{
min = distance[j];
nearvertex = j;
}
}
//edge.Add(min); edge array is unnecessary.
for (int i = 0; i < graph.GetLength(0); i++)
{
// you are using 0 as un-reachable distance value in your graph array, so you should check it.
if (distance[nearvertex] + graph[nearvertex][i] < distance[i] && graph[nearvertex][i] > 0 && !vertex.Contains(i))
{
distance[i] = distance[nearvertex] + graph[nearvertex][i];
vertex.Add(nearvertex);
}
}
//distance[nearvertex] = -1; No change required after refreshing distance array.
nodes--;
}
// shortest path from source ( 0 ) will be restored in distance array.
foreach (var i in distance)
Console.WriteLine(i);
}
Sample Result
// 0, 1, 7, 0, 0
// 0, 0, 4, 4, 1
// 0, 0, 0, 3, 2
// 0, 0, 0, 0, 5
// 0, 0, 0, 0, 0
0 // source vertex
1 // 0 -> 1
5 // 0 -> 1 -> 2
5 // 0 -> 1 -> 3
2 // 0 -> 1 -> 4

How can I delete rows and columns that only contains zero's in an 2d array?

I have an 2d array and I have no idea how I can delete the rows and columns from it in which are only zero's.
int [,] test = { {0, 0, 0, 0},
{0, 0, 1, 1},
{0, 1, 1, 0},
{0, 0, 0, 0} }
int row = pieces.GetLength(0);
int col = pieces.GetLength(1);
for (int y = 0; y < row; y++)
{
for (int x = 0; x < col; x++)
{
if (pieces[y,x] == 0)
{
}
}
}
So I want it to be this:
int [,] test = { {0, 1, 1},
{1, 1, 0}}
Here this will remove every Column/Row with only zero
int[][] test = { new int[]{0, 0, 0, 0},
new int[]{0, 0, 1, 1},
new int[]{0, 1, 1, 0},
new int[]{0, 0, 0, 0} };
var result =
Transpose(Transpose(test.Where(row => !row.All(item => item == 0)).ToArray()).Where(row => !row.All(item => item == 0)).ToArray())
.ToArray();
This basically selects the rows where there isn't a single 0. Now transpose the matrix(its easier to not select rows than not selecting columns) and again select every row where there isn't any 0(meaning there is at least a 1 we need), now transpose back to original order.
here are the helper methods
static int[][] Transpose(int[][] originalArray)
{
int w = originalArray.Length;
int h = originalArray[0].Length;
int[][] result = CreateJaggedArray<int[][]>(h, w);
for (int i = 0; i < originalArray.Length; i++)
for (int j = 0; j < originalArray[i].Length; j++)
{
result[j][i] = originalArray[i][j];
}
return result;
}
static T CreateJaggedArray<T>(params int[] lengths)
{
return (T)InitializeJaggedArray(typeof(T).GetElementType(), 0, lengths);
}
static object InitializeJaggedArray(Type type, int index, int[] lengths)
{
Array array = Array.CreateInstance(type, lengths[index]);
Type elementType = type.GetElementType();
if (elementType != null)
{
for (int i = 0; i < lengths[index]; i++)
{
array.SetValue(
InitializeJaggedArray(elementType, index + 1, lengths), i);
}
}
return array;
}
you can convert them to extensions if you want since they are static anyway.
Check out the complete example at dotnetfiddle
Ok i created a code, that will first create List<int> out of each row and column, and add its indexes to another List<int> that will mark columns and rows at which '1' does appear. This code uses Linq, to check .Contains() if 1 does exists. Rest should be fairly easy to read.
int[,] test = { {0, 0, 0, 0},
{0, 0, 1, 1},
{0, 1, 1, 0},
{0, 0, 0, 0}};
//get size
int columns = test.GetLength(0);
int rows = test.Length / columns;
//create lists
List<int> nonZeroRows = new List<int>();
List<int> nonZeroColumns = new List<int>();
for (int row = 0; row < rows; row++)
{
List<int> rowAsList = new List<int>();
List<int> columnAsList = new List<int>();
for (int col = 0; col < columns; col++)
{
rowAsList.Add(test[row, col]);
columnAsList.Add(test[col, row]);
}
//check if row & column contains 1
if(rowAsList.Contains(1))
{
nonZeroRows.Add(row);
}
if (columnAsList.Contains(1))
{
nonZeroColumns.Add(row);
}
}
//create new array
int[,] result = new int[nonZeroRows.Count, nonZeroColumns.Count];
int irow = 0;
foreach(int row_id in nonZeroRows)
{
int icol = 0;
foreach (int col_id in nonZeroColumns)
{
result[irow,icol] = test[row_id, col_id];
icol++;
}
irow++;
}

Square with Maximum Sum

I am learning C#, and I am doing Multidimensional Arrays at the moment. I want to write a program that reads a matrix and then finds the biggest sum of 2x2 submatrix and prints it.
int[] dimensions = Console.ReadLine()
.Split(", ", StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
int rows = dimensions[0];
int columns = dimensions[1];
int[,] matrix = new int[rows,columns];
for (int i = 0; i < rows; i++)
{
int[] numbers = Console.ReadLine()
.Split(", ", StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToArray();
for (int j = 0; j < columns; j++)
{
matrix[i, j] = numbers[j];
}
}
int maxSum = int.MinValue;
int selectedRow = -1;
int selectedCol = -1;
for (int row = 0; row < matrix.GetLength(0) - 1; row++)
{
for (int col = 0; col < matrix.GetLength(1) - 1; col++)
{
int currentSum = matrix[row, col] + matrix[row, col + 1] + matrix[row + 1, col] + matrix[row + 1, col + 1];
if (currentSum > maxSum)
{
maxSum = currentSum;
selectedRow = row;
selectedCol = col;
}
}
}
Console.WriteLine($"{matrix[selectedRow, selectedCol]} {matrix[selectedRow, selectedCol + 1]}");
Console.WriteLine($"{matrix[selectedRow + 1, selectedCol]} {matrix[selectedRow + 1, selectedCol + 1]}");
Console.WriteLine(maxSum);
So, I read the matrix, but I am not sure how to start finding the submatrices and compare their sums. I would be very grateful if you could give me some hints.
You need to check values only current, under positions of your i and current, right positions of your j.
I mean it will check like this:
[7,1] [1,3] [3,3]
[1,3] [3,9] [9,8]
And so on.
After every compare, calculate sum of this 2x2 matrix and save it to dictionary.
For return, you just need to find the max value of key and get value of it key.
public class MatrixTest
{
public static IEnumerable<object[]> TestData =>
new List<object[]>
{
new object[]
{
new int[,]
{
{7, 1, 3, 3, 2, 1},
{1, 3, 9, 8, 5, 6},
{4, 6, 7, 9, 1, 0}
},
new int[,]
{
{9, 8},
{7, 9}
},
33
},
new object[]
{
new int[,]
{
{10, 11, 12, 13},
{14, 15, 16, 17}
},
new int[,]
{
{12, 13},
{16, 17}
},
58
}
};
[Theory]
[MemberData(nameof(TestData))]
public void Test(int[,] input, int[,] expectedArray, int expectedSum)
{
MatrixHandler m = new MatrixHandler();
var resp = m.GetMax2x2Matrix(input);
resp.Item1.Should().Be(expectedSum);
resp.Item2.Should().BeEquivalentTo(expectedArray);
}
}
public class MatrixHandler
{
public (int, int[,]) GetMax2x2Matrix(int[,] source)
{
var sumsPlusTempArrays = new Dictionary<int, int[,]>();
int[,] temp;
int sum = 0;
for (int i = 0, n0 = source.GetLength(0) - 1; i <= n0; i++)
{
for (int j = 0, n1 = source.GetLength(1) - 1; j <= n1; j++)
{
if (i + 1 <= n0 && j + 1 <= n1)
{
temp = new int[2,2];
temp[0, 0] = source[i, j];
temp[0, 1] = source[i, j + 1];
temp[1, 0] = source[i + 1, j];
temp[1, 1] = source[i + 1, j + 1];
sum = CalculateSum(temp);
sumsPlusTempArrays.TryAdd(sum, temp);
}
}
}
var key = sumsPlusTempArrays.Select(x => x.Key).Max();
var value = sumsPlusTempArrays[key];
return (key, value);
}
private int CalculateSum(int[,] source)
{
int sum = 0;
for (int i = 0, n0 = source.GetLength(0); i < n0; i++)
{
for (int j = 0, n1 = source.GetLength(1); j < n1; j++)
{
sum += source[i, j];
}
}
return sum;
}
}

How can I create a bool 3D array of char, int, int in C#

I am trying to create a bool 3d array which contains char, int, and int such as
Table['a', 0, 5] = false;
Table['b', 1, 4] = true;
I created the 2d but not able to create the 3d
var cells = new bool[word.Length, word.Length];
for (int i = 0; i < word.Length; i++)
{
for (int j = 0; j < word.Length; j++)
{
cells[i, j] = false; // what to write here
}
}
You could use a dictionary of tuples and bool's, like this:
var t = new Dictionary<Tuple<char, int, int>, bool>();
t.Add(Tuple.Create<char, int, int>('a', 0, 5), false);
t.Add(Tuple.Create<char, int, int>('b', 1, 4), true);
// Prints false
Console.WriteLine("a, 0, 5 = {0}", t[Tuple.Create<char, int, int>('a', 0, 5)]);
// Prints true
Console.WriteLine("b, 1, 4 = {0}", t[Tuple.Create<char, int, int>('b', 1, 4)]);
If you insist on 3D array, I suggest something like this:
// ['a'..'z', 0..word.Length - 1, 0..word.Length - 1] bool array
// (first index is not zero-based)
bool[,,]cells = (bool[,,]) Array.CreateInstance(
typeof(bool), // Array items type
new int[] { 26, word.Length, word.Length }, // Sizes
new int[] { 'a', 0, 0 }); // Lower bounds
...
// Single item addressing
cells['b', 1, 4] = true;
...
// Loop over all the array's items
for (int i = cells.GetLowerBound(0); i <= cells.GetUpperBound(0); ++i)
for (int j = cells.GetLowerBound(1); j <= cells.GetUpperBound(1); ++j)
for (int k = cells.GetLowerBound(2); k <= cells.GetUpperBound(2); ++k) {
// ... cells[i, j, k] ...
}
It seems that you want to start the first index from 'a', not from 0 that's why I've provided that complex call. Please notice, that you don't have to initialize array's items to false.
See
https://msdn.microsoft.com/en-us/library/x836773a(v=vs.110).aspx
for details

Apply Dijkstra in a real sparse matrix in C#

I Have this code to get "shortest path" using Dijkstra
but I know a real problem involves sparse matrices (matrix populated primarily with zeros).
Is there a way to improve efficiency in this code?
If so what improvements?¡
The graph is:
using System;
namespace DijkstraAlgorithm
{
/*
* Dijkstra's algorithm, named after its discoverer, Dutch computer scientist Edsger Dijkstra,
* is a greedy algorithm that solves the single-source shortest path problem for a directed graph
* with non negative edge weights. For example, if the vertices (nodes) of the graph represent cities
* and edge weights represent driving distances between pairs of cities connected by a direct road,
* Dijkstra's algorithm can be used to find the shortest route between two cities. Also, this algorithm
* can be used for shortest path to destination in traffic network.
* Pseudocode
function Dijkstra(L[1..n, 1..n]) : array [2..n]
array D[2..n]
set C
C <- {2, 3, 4, 5, 6, …, n}
for i <- 2 to n
D[i] <- L[1,i]
repeat n - 2 times
v <- C // minimum D[v] extract to C
v <- C - {v}
for each w in C do
D[w] <- min(D[w], D[v] + L[v,w])
return D
*/
class Dijkstra
{
private int rank = 0;
private int[,] L;
private int[] C;
public int[] D;
private int trank = 0;
public Dijkstra(int paramRank,int [,]paramArray)
{
L = new int[paramRank, paramRank];
C = new int[paramRank];
D = new int[paramRank];
rank = paramRank;
for (int i = 0; i < rank; i++)
{
for (int j = 0; j < rank; j++) {
L[i, j] = paramArray[i, j];
}
}
for (int i = 0; i < rank; i++)
{
C[i] = i;
}
C[0] = -1;
for (int i = 1; i < rank; i++)
D[i] = L[0, i];
}
public void DijkstraSolving()
{
int minValue = Int32.MaxValue;
int minNode = 0;
for (int i = 0; i < rank; i++)
{
if (C[i] == -1)
continue;
if (D[i] > 0 && D[i] < minValue)
{
minValue = D[i];
minNode = i;
}
}
C[minNode] = -1;
for (int i = 0; i < rank; i++)
{
if (L[minNode, i] < 0)
continue;
if (D[i] < 0) {
D[i] = minValue + L[minNode, i];
continue;
}
if ((D[minNode] + L[minNode, i]) < D[i])
D[i] = minValue+ L[minNode, i];
}
}
public void Run()
{
for (trank = 1; trank <rank; trank++)
{
DijkstraSolving();
Console.WriteLine("iteration" + trank);
for (int i = 0; i < rank; i++)
Console.Write(D[i] + " ");
Console.WriteLine("");
for (int i = 0; i < rank; i++)
Console.Write(C[i] + " ");
Console.WriteLine("");
}
}
static void Main(string[] args)
{
int[,] L ={
{-1, 5, -1, -1, -1, 3, -1, -1},
{ 5, -1, 2, -1, -1, -1, 3, -1},
{-1, 2, -1, 6, -1, -1, -1, 10},
{-1, -1, 6, -1, 3, -1, -1, -1},
{-1, -1, -1, 3, -1, 8, -1, 5},
{ 3, -1, -1, -1, 8, -1, 7, -1},
{-1, 3, -1, -1, -1, 7, -1, 2},
{-1, -1, 10, -1, 5, -1, 2, -1}
};
Dijkstra clss = new Dijkstra((int)Math.Sqrt(L.Length),L);
clss.Run();
Console.WriteLine("Solution is");
foreach (int i in clss.D)
{
Console.WriteLine(i);
}
Console.WriteLine("Press Enter for exit.");
Console.Read();
}
}
}
In the code the matrix is an easy one, but if I have an sparse one...??
One possible improvement would be to stop using an array for the graph, and instead use a SparseMatrix class, which will result in better iteration over the matrix's entries.
You can probably find several libraries that provide SparseMatrix implementations:
http://www.extremeoptimization.com/QuickStart/SparseMatricesCS.aspx
http://sparsematrix.codeplex.com/
http://metanumerics.codeplex.com/
Another improvement might be to use multi-threads, but since each iteration of the Dijkstra algorithm is based on the previous iteration, that would have to be done extremely carefully.

Categories