I'm trying to implement Floyd-Warshall algorithm (all pairs shortest path). In the code below, when I enter some numbers, it gives the last number as input. I know the code is not complete.
Now what should I do to print shortest paths for each i and j? Or what do you suggest to me to do to complete this code. Thanks.
private void button10_Click(object sender, EventArgs e)
{
string ab = textBox11.Text;
int matrixDimention = Convert.ToInt32(ab);
int[,] intValues = new int[matrixDimention, matrixDimention];
string[] splitValues = textBox9.Text.Split(',');
for (int i = 0; i < splitValues.Length; i++)
intValues[i / (matrixDimention), i % (matrixDimention)] = Convert.ToInt32(splitValues[i]);
string displayString = "";
for (int inner = 0; inner < intValues.GetLength(0); inner++)
{
for (int outer = 0; outer < intValues.GetLength(0); outer++)
displayString += String.Format("{0}\t", intValues[inner, outer]);
displayString += Environment.NewLine;
}
int n = (int)Math.Pow(matrixDimention, 2);
string strn = n.ToString();
MessageBox.Show("matrix"+strn+ "in" + strn + "is\n\n\n" +displayString);
////before this line i wrote the codes to get the numbers that user enter in textbox and put it in an 2d array
for (int k = 1; k < n+1; k++)
for (int i = 1; i < n+1; i++)
for (int j = 1; j < n+1; j++)
if (intValues[i, j] > intValues[i, k] + intValues[k, j])
{
intValues[i, j] = intValues[i, k] + intValues[k, j];
string str_intvalues = intValues[i, j].ToString();
MessageBox.Show("Shortest Path from i to j is: " + str_intvalues);
}
else
{
string str_intvalues = intValues[i, j].ToString();
MessageBox.Show("Shortest Path from i to j is: " + str_intvalues);
}
}
To be on a same page, let me show you the Floyd-Warshall algorithm first:
Let us have a graph, described by matrix D, where D[i][j] is the length of edge (i -> j) (from graph's vertex with index i to the vertex with index j).
Matrix D has the size of N * N, where N is total number of vertices in graph, because we can reach the maximum of paths by connecting each graph's vertex to each other.
Also we'll need matrix R, where we will store shortest paths (R[i][j] contains the index of a next vertex in the shortest path, starting at vertex i and ending at vertex j).
Matrix R has the same size as D.
The Floyd-Warshall algorithm performs these steps:
initialize the matrix of all the paths between any two pairs or vertices in a graph with the edge's end vertex (this is important, since this value will be used for path reconstruction)
for each pair of connected vertices (read: for each edge (u -> v)), u and v, find the vertex, which forms shortest path between them: if the vertex k defines two valid edges (u -> k) and (k -> v) (if they are present in the graph), which are together shorter than path (u -> v), then assume the shortest path between u and v lies through k; set the shortest pivot point in matrix R for edge (u -> v) to be the corresponding pivot point for edge (u -> k)
Now that we are on a same page with definitions, algorithm can be implemented like this:
// Initialise the routes matrix R
for (int i = 0; i < N; i++) {
for (int t = 0; t < N; t++) {
R[i][t] = t;
}
}
// Floyd-Warshall algorithm:
for (int k = 0; k < N; k++) {
for (int u = 0; u < N; u++) {
for (int v = 0; v < N; v++) {
if (D[u, v] > D[u, k] + D[k, v]) {
D[u, v] = D[u, k] + D[k, v];
R[u, v] = R[u, k];
}
}
}
}
But how do we read the matrix D?
Let us have a graph:
In GraphViz it would be described as follows:
digraph G {
0->2 [label = "1"];
2->3 [label = "5"];
3->1 [label = "2"];
1->2 [label = "6"];
1->0 [label = "7"];
}
We first create a two-dimensional array of size 4 (since there are exactly 4 vertices in our graph).
We initialize its main diagonal (the items, whose indices are equal, for ex. G[0, 0], G[1, 1], etc.) with zeros, because
the shortest path from vertex to itself has the length 0 and the other elements with a very large number (to indicate there is no edge or an infinitely long edge between them). The defined elements, corresponding to graph's edges, we fill with edges' lengths:
int N = 4;
int[,] D = new int[N, N];
for (int i = 0; i < N; i++) {
for (int t = 0; t < N; t++) {
if (i == t) {
D[i, t] = 0;
} else {
D[i, t] = 9999;
}
}
}
D[0, 2] = 1;
D[1, 0] = 7;
D[1, 2] = 6;
D[2, 3] = 5;
D[3, 1] = 2;
After the algorithm run, the matrix R will be filled with vertices' indices, describing shortest paths between them. In order to reconstruct the path from vertex u to vertex v, you need follow the elements of matrix R:
List<Int32> Path = new List<Int32>();
while (start != end)
{
Path.Add(start);
start = R[start, end];
}
Path.Add(end);
The whole code could be wrapped in a couple of methods:
using System;
using System.Collections.Generic;
public class FloydWarshallPathFinder {
private int N;
private int[,] D;
private int[,] R;
public FloydWarshallPathFinder(int NumberOfVertices, int[,] EdgesLengths) {
N = NumberOfVertices;
D = EdgesLengths;
R = null;
}
public int[,] FindAllPaths() {
R = new int[N, N];
for (int i = 0; i < N; i++)
{
for (int t = 0; t < N; t++)
{
R[i, t] = t;
}
}
for (int k = 0; k < N; k++)
{
for (int v = 0; v < N; v++)
{
for (int u = 0; u < N; u++)
{
if (D[u, k] + D[k, v] < D[u, v])
{
D[u, v] = D[u, k] + D[k, v];
R[u, v] = R[u, k];
}
}
}
}
return R;
}
public List<Int32> FindShortestPath(int start, int end) {
if (R == null) {
FindAllPaths();
}
List<Int32> Path = new List<Int32>();
while (start != end)
{
Path.Add(start);
start = R[start, end];
}
Path.Add(end);
return Path;
}
}
public class MainClass
{
public static void Main()
{
int N = 4;
int[,] D = new int[N, N];
for (int i = 0; i < N; i++) {
for (int t = 0; t < N; t++) {
if (i == t) {
D[i, t] = 0;
} else {
D[i, t] = 9999;
}
}
}
D[0, 2] = 1;
D[1, 0] = 7;
D[1, 2] = 6;
D[2, 3] = 5;
D[3, 1] = 2;
FloydWarshallPathFinder pathFinder = new FloydWarshallPathFinder(N, D);
int start = 0;
int end = 1;
Console.WriteLine("Path: {0}", String.Join(" -> ", pathFinder.FindShortestPath(start, end).ToArray()));
}
}
You can read 'bout this algorithm on wikipedia and get some data structures generated automatically here
When you are using Floyd algorithm, it saves only the shortest distance from node i to node j of your graph. So, you can also save the path to nodes. How to do it?
one of the ways to implement it - is to save the parent (the node, which is a previous node for current node in the path) node. You are to make another matrix, which will contain paths. It could look like this:
int[,] pathS = new int[matrixDimention, matrixDimention];
for (int i = 0; i < splitValues.Length; i++){
intValues[i / (matrixDimention), i % (matrixDimention)] = Convert.ToInt32(splitValues[i]);
pathS[i / (matrixDimention), i % (matrixDimention)] = -1;
}
.....
for (int k = 1; k < n+1; k++)
for (int i = 1; i < n+1; i++)
for (int j = 1; j < n+1; j++)
if (intValues[i, j] > intValues[i, k] + intValues[k, j]){
intValues[i, j] = intValues[i, k] + intValues[k, j];
pathS[i,j] = k;
string str_intvalues = intValues[i, j].ToString();
MessageBox.Show("Shortest Path from i to j is: " + str_intvalues);
}
else{
string str_intvalues = intValues[i, j].ToString();
MessageBox.Show("Shortest Path from i to j is: " + str_intvalues);
}
Now you have additional pathS array, which contains intermidiate paths between nodes i and j. For better understandning you should consider, that pathS[i,j] is a node between this two nodes (e.g. i -> [k] -> j). But your path could be longer, than 3 nodes (that's why I wrote node k in [] braces). So, now you have to check path between i and k - pathS[i,k] and path between k and j - pathS[k,j]. And do the same recursively, until pathS between some i and j equals to "-1".
Related
I am trying to find the smallest number in a dynamic 2d array but i have
hit a block and cannot figure out how this is done. I have done all the set up and populated with values.
using System;
namespace _2D_Array
{
class Program
{
static void Main(string[] args)
{
// Create integers n and r and set up the 2D array
int n = 5;
int[,] a;
int R = 50;
int x;
a = new int[n + 1, n + 1];
// Create number input randomizer
Random r = new Random();
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
a[i, j] = r.Next(1, R);
// Print array with random numbers to screen to check set up is correct for i and j
Console.Write(" ");
for (int i = 1; i <= n; ++i)
Console.Write(i.ToString("00" + " "));
Console.WriteLine();
Console.WriteLine();
for (int i = 1; i <= n; ++i)
{
Console.Write(i.ToString("00" + " "));
for (int j = 1; j <= n; ++j)
Console.Write(a[i, j].ToString("00" + " "));
Console.WriteLine();
}
// Get Search Value
Console.Write("What's the value to look for? ");
x = int.Parse(Console.ReadLine());
// look through the array
for (int i = 1; i <= n; ++i)
{
for (int j = 1; j <= n; ++j)
// If the element is found
if (a[i, j] == x)
{
Console.Write("Element found at (" + i + ", " + j + ")\n");
}
}
Console.Write(" Element not found");
```
This is all i have so far. in the end i want to have the smallest
value from a set of random numbers set in my 5x5 array.
First of all, format out your code: hard to read code is hard to debug.
Often, we can query array with a help of Linq:
using System.Linq;
...
int min = a.OfType<int>().Min();
Console.Write($"The smallest element is {min}");
If you want good old nested loops:
// not 0! What if min = 123?
// Another possibility is min = a[0, 0]; - min is the 1st item
int min = int.MaxValue;
// note a.GetLength(0), a.GetLength(0): n is redundant here
// and there's no guarantee that we have a square array
for (int r = 0; r < a.GetLength(0); ++r)
for (int c = 0; c < a.GetLength(1); ++c)
min = Math.Min(min, a[r, c]);
Console.Write($"The smallest element is {min}");
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
does anyone know how to convert a List to a 3D Array?. My input list will actually always be a "flattened" verison of a 3D Array, so I will always know the arrays dimensions. Any clues would be great
T[,] output = new T[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
output[i, j] = input[i * width + j];
}
}
This is to convert a List/Array to a 2D Array, but I dont seem to wrap my head around to convert to a 3D Array
You will need to know each dimension of the three of the 3D array. Lets say they are d1, d2, and d3, then you can use this code to get the array you want, assuming an int array:
int i, j, k, p;
int[,,] Arr = new int[d1, d2, d3];
p = 0;
for (i = 0; i < d1; i++)
for (j = 0; j < d2; j++)
for (k = 0; k < d3; k++)
a[i, j, k] = lst[p++];
If you want a solution similar to you example you can try this:
int i, j, k;
int[,,] Arr = new int[d1, d2, d3];
for (i = 0; i < d1; i++)
for (j = 0; j < d2; j++)
for (k = 0; k < d3; k++)
a[i, j, k] = lst[i * d2 * d3 + j * d3 + k];
You just need to know which order the items were stored in when going from an array to a list, and from that you can see how to calculate the index into the list:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
// N.B. You will have to pick which order the dimensions go in.
var ni = 4;
var nj = 3;
var nk = 2;
// Make a list that could be interpreted as a 3-d array:
var x = new List<string>();
for (int k = 0; k < nk; k++)
{
for (int j = 0; j < nj; j++)
{
for (int i = 0; i < ni; i++)
{
x.Add($"{k}-{j}-{i}");
}
}
}
Console.WriteLine(string.Join(", ", x));
// Copy the content of the list to a 3-d array:
string[,,] array1 = new string[nk, nj, ni];
for (int k = 0; k < nk; k++)
{
for (int j = 0; j < nj; j++)
{
for (int i = 0; i < ni; i++)
{
var idx = i + j * (nj + 1) + k * (nk + 1) * (nj + 1);
array1[k, j, i] = x[idx];
Console.Write(array1[k, j, i] + ", ");
}
}
}
Console.ReadLine();
}
}
}
Which outputs, for confirmation,
0-0-0, 0-0-1, 0-0-2, 0-0-3, 0-1-0, 0-1-1, 0-1-2, 0-1-3, 0-2-0, 0-2-1, 0-2-2, 0-2-3, 1-0-0, 1-0-1, 1-0-2, 1-0-3, 1-1-0, 1-1-1, 1-1-2, 1-1-3, 1-2-0, 1-2-1, 1-2-2, 1-2-3
0-0-0, 0-0-1, 0-0-2, 0-0-3, 0-1-0, 0-1-1, 0-1-2, 0-1-3, 0-2-0, 0-2-1, 0-2-2, 0-2-3, 1-0-0, 1-0-1, 1-0-2, 1-0-3, 1-1-0, 1-1-1, 1-1-2, 1-1-3, 1-2-0, 1-2-1, 1-2-2, 1-2-3,
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 3; k++)
a[i, j ,k] = x;
If matrix A of size (3x3), then should i use the method of finding determinants, like grabbing the rows and column of first element and removing it from the array 2D array to get the remaining elements and then moving to the next element and repeating the same steps ?
[{1,2,3},
{4,5,6},
{7,8,9}]
I finally was able to do it, here's what I did :
enter image description here
class program
{
public static void Main()
{
int[,] arr = new int[3, 3];
Console.WriteLine("Enter elements of " + (arr.GetUpperBound(0) + 1) + "x" + (arr.GetUpperBound(1) + 1) + " matrix:");
for (int i = 0; i < (arr.GetUpperBound(0) + 1); i++)
{
for (int j = 0; j < (arr.GetUpperBound(1) + 1); j++)
{
arr[i, j] = Convert.ToInt32(Console.ReadLine());
}
}
Console.WriteLine("Matrix entered: ");
for (int i = 0; i < (arr.GetUpperBound(0) + 1); i++)
{
for (int j = 0; j < (arr.GetUpperBound(1) + 1); j++)
{
Console.Write("\t" + arr[i, j]);
}
Console.WriteLine();
}
Console.WriteLine("Possible sub-matrices: ");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j< 3; j++)
{
TrimArray(i,j,arr);
}
}
}
public static int[,] TrimArray(int row, int column, int[,] original)
{
int[,] resultant = new int[original.GetLength(0) - 1, original.GetLength(1) - 1];
for (int i = 0, j = 0; i < original.GetLength(0); i++)
{
if (i == row)
continue;
for (int k = 0, u = 0; k < original.GetLength(1); k++)
{
if (k == column)
continue;
resultant[j, u] = original[i, k];
u++;
}
j++;
}
Console.WriteLine();
for (int i = 0; i < 2; i++)
{
for (int j = 0; j< 2; j++)
{
Console.Write("\t"+resultant[i,j]);
}
Console.WriteLine();
}
return resultant;
}
}
I did this for you yesterday, I created a method that will return a square matrix, given a parent matrix and the length.
static void Main(string[] args)
{
int[][] parentMatrix = new int[][]
{
new int [] { 1, 2, 3 },
new int [] { 4, 5, 6 },
new int [] { 7, 8, 9 }
};
var chunks = GetSubMatrices(parentMatrix, 2);
Console.WriteLine(chunks);
}
static List<int[][]> GetSubMatrices(int[][] parentMatrix, int m)
{
int n = parentMatrix.Length > m ? parentMatrix.Length : throw new InvalidOperationException("You can't use a matrix smaller than the chunk size");
var chunks = new List<int[][]>();
int movLimit = n - m + 1;
var allCount = Math.Pow(movLimit, 2);
for (int selRow = 0; selRow < movLimit; selRow ++)
{
for (int selCol = 0; selCol < movLimit; selCol ++)
{
// this is start position of the chunk
var chunk = new int[m][];
for (int row = 0; row < m; row++)
{
chunk[row] = new int[m];
for (int col = 0; col < m; col++)
{
chunk[row][col] = parentMatrix[selRow + row][selCol + col];
}
}
chunks.Add(chunk);
}
}
return chunks;
}
If you have any problems using it, you can simply comment below.
I needed to solve a problem like and came up with this answer. Hope it adds to your library of answers. If the submatrix specified is not greater than 1, do nothing.
public static void GetSubMatrixes(int[,] arr, int size)
{
int parentMatrixRowLength = arr.GetLength(0);
int parentMatrixColLength = arr.GetLength(1);
var overall = new List<object>();
if(size > 1)
{
for (int i = 0; i < parentMatrixRowLength; i++)
{
//get the columns
for (int j = 0; j < parentMatrixColLength; j++)
{
var subMatrix = new int[size, size];
/*if the new matrix starts from second to the last value in either the row(horizontal or column)
* do not proceed, go to the row or column in the parent matrix
* */
if (j < parentMatrixColLength - (size - 1) && i < parentMatrixRowLength - (size - 1))
{
//add
for (int m = 0; m < subMatrix.GetLength(0); m++)
{
for (int n = 0; n < subMatrix.GetLength(1); n++)
{
/*check the sum of current column value and the sum of the current row value
* of the parent column length and row length if it goes out of bounds
*/
var row = i + m; var col = j + n;
//actual check here
if (row < parentMatrixRowLength && col < parentMatrixColLength)
{
subMatrix[m, n] = arr[i + m, j + n];
}
}
}
overall.Add(subMatrix);
}
}
}
//display the sub matrixes here
for (int i = 0; i < overall.Count; i++)
{
var matrix = overall[i] as int[,];
for (int y = 0; y < matrix.GetLength(0); y++)
{
for (int x = 0; x < matrix.GetLength(1); x++)
{
Console.Write(string.Format("{0} ", matrix[y, x]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
Console.WriteLine();
}
}
}
enter code here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testing_random
{
class Program
{
static void Main(string[] args)
{
int n = 4;
int[,] a = new int[n,n];//declaring the matrix
Random o = new Random();
a[0,0] = o.Next(n);
for (int i = 1; i < n; i++)//filling the first line
{
int d = 1;
while (d != 0)
{
a[i,0] = o.Next(n);
d = 0;
for (int j = 0; j < i; j++)
if (a[i,0] == a[j,0])
d++;
}
}
for (int i = 1; i < n; i++)//filing the first column
{
int d = 1;
while (d != 0)
{
a[0, i] = o.Next(n);
d = 0;
for (int j = 0; j < i; j++)
if (a[0, i] == a[0, j])
d++;
}
}
for (int k = 1; k < n; k++)//filling the rest of the matrix
for (int i = 1; i < n; i++)
{
int d = 1;
while (d != 0)
{
a[i, k] = o.Next(n);
d = 0;
for (int j = 0; j < i; j++)
if (a[i, k] == a[j, k])
d++;
for (int j = 0; j < k; j++)
if (a[i, k] == a[i, j])
d++;
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
Console.Write("{0} ", a[i, j]);
Console.WriteLine();
}
Console.ReadLine();
}
}
}
The output should be a matrix of 4*4 where each column and each line contains each number once.
The problem is when i run the code, not every time i get an output, i think the problem is not every set of first line and column can give a matrix as required the i get into an unending loop.
what i want to do is limit the running time of the application to 100 ms per example,so if the matrix is not filled,the program restarts
What piece of code am i missing?
replace the while( d != 0 ) with a loop which counts up to a certain very large maximum number of iterations. (Try 1000, 100000, whatever.)
Are you trying to randomly insert numbers between 1-4 in the first line of the array? If so there is a much easier way to do it.
You can generate the 4 numbers to be inserted into the array and then just look through the first line of the array and set each value.
Random rnd = new Random();
var randomNumbers = Enumerable.Range(1, 4).OrderBy(i => rnd.Next()).ToArray();
for (int i = 0; i < n; i++)
{
a[i, 0] = randomNumbers[i];
}
I have problems finding an implementation of closest match strings for .net
I would like to match a list of strings, example:
input string: "Publiczna Szkoła Podstawowa im. Bolesława Chrobrego w Wąsoszu"
List of strings:
Publiczna Szkoła Podstawowa im. B. Chrobrego w Wąsoszu
Szkoła Podstawowa Specjalna
Szkoła Podstawowa im.Henryka Sienkiewicza w Wąsoszu
Szkoła Podstawowa im. Romualda Traugutta w Wąsoszu Górnym
This would clearly need to be matched with "Publiczna Szkoła Podstawowa im. B. Chrobrego w Wąsoszu".
What algorithms are there available for .net?
Edit distance
Edit distance is a way of quantifying how dissimilar two strings
(e.g., words) are to one another by counting the minimum number of
operations required to transform one string into the other.
Levenshtein distance
Informally, the Levenshtein distance between two words is the minimum
number of single-character edits (i.e. insertions, deletions or
substitutions) required to change one word into the other.
Fast, memory efficient Levenshtein algorithm
C# Levenshtein
using System;
/// <summary>
/// Contains approximate string matching
/// </summary>
static class LevenshteinDistance
{
/// <summary>
/// Compute the distance between two strings.
/// </summary>
public static int Compute(string s, string t)
{
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
// Step 1
if (n == 0)
{
return m;
}
if (m == 0)
{
return n;
}
// Step 2
for (int i = 0; i <= n; d[i, 0] = i++)
{
}
for (int j = 0; j <= m; d[0, j] = j++)
{
}
// Step 3
for (int i = 1; i <= n; i++)
{
//Step 4
for (int j = 1; j <= m; j++)
{
// Step 5
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
// Step 6
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
// Step 7
return d[n, m];
}
}
class Program
{
static void Main()
{
Console.WriteLine(LevenshteinDistance.Compute("aunt", "ant"));
Console.WriteLine(LevenshteinDistance.Compute("Sam", "Samantha"));
Console.WriteLine(LevenshteinDistance.Compute("flomax", "volmax"));
}
}
.NET does not supply anything out of the box - you need to implement a an Edit Distance algorithm yourself. For example, you can use Levenshtein Distance, like this:
// This code is an implementation of the pseudocode from the Wikipedia,
// showing a naive implementation.
// You should research an algorithm with better space complexity.
public static int LevenshteinDistance(string s, string t) {
int n = s.Length;
int m = t.Length;
int[,] d = new int[n + 1, m + 1];
if (n == 0) {
return m;
}
if (m == 0) {
return n;
}
for (int i = 0; i <= n; d[i, 0] = i++)
;
for (int j = 0; j <= m; d[0, j] = j++)
;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;
d[i, j] = Math.Min(
Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
d[i - 1, j - 1] + cost);
}
}
return d[n, m];
}
Call LevenshteinDistance(targetString, possible[i]) for each i, then pick the string possible[i] for which LevenshteinDistance returns the smallest value.
Late to the party, but I had a similar requirement to #Ali123:
"ECM" is closer to "Open form for ECM" than "transcribe" phonetically
I found a simple solution that works for my use case, which is comparing sentences, and finding the sentence that has the most words in common:
public static string FindBestMatch(string stringToCompare, IEnumerable<string> strs) {
HashSet<string> strCompareHash = stringToCompare.Split(' ').ToHashSet();
int maxIntersectCount = 0;
string bestMatch = string.Empty;
foreach (string str in strs)
{
HashSet<string> strHash = str.Split(' ').ToHashSet();
int intersectCount = strCompareHash.Intersect(strCompareHash).Count();
if (intersectCount > maxIntersectCount)
{
maxIntersectCount = intersectCount;
bestMatch = str;
}
}
return bestMatch;
}