Related
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
Let's say I have an array with integers, which represent the daily changes in the price of a stock, as an example the following array:
[3, -1, -4, 1, 5, -9, 2, 6].
How would I find the amount of subarrays which have a sum between two values (lower and upper, so l <= s <= u), such as -1 (=lower) and 0 (=upper)? In this case, the answer would be 5. You can have the subarrays
[3, -1, -4, 1]
[-1]
[-1, -4, 1, 5, -9, 2, 6]
[1, 5, -9, 2]
[-9, 2, 6]
Another example array would be:
[4, 2, 2, -6, 7]
with lower bound 3, upper bound 4. The answer to this would be 3. I have tried the following very naïve approach, which I'm certain there are many faster alternatives for. I'm wondering how I can solve this problem faster, with divide-and-conquer or possibly through dynamically programming.
Class
public class Stock
{
public int sequenceLength;
public int[] prices;
public int lowerBound;
public int upperBound;
public int count = 0;
public Stock()
{
sequenceLength = Int32.Parse(Console.ReadLine());
prices = new int[sequenceLength];
var split = Console.ReadLine();
var splitSpace = split.Split(' ');
for (int i = 0; i < sequenceLength; i++)
prices[i] = Int32.Parse(splitSpace[i]);
lowerBound = Int32.Parse(Console.ReadLine());
upperBound = Int32.Parse(Console.ReadLine());
}
}
Usage
static void Main(string[] args)
{
int testcases = Int32.Parse(Console.ReadLine());
Stock[] stock = new Stock[testcases];
for (int i = 0; i < testcases; i++)
stock[i] = new Stock();
int count = 0;
for (int i = 0; i < stock.Length; i++)
{
for (int j = 0; j < stock[i].sequenceLength - 1; j++)
{
int sum = stock[i].prices[j];
if (sum >= stock[i].lowerBound && sum <= stock[i].upperBound)
count++;
for (int k = j + 1; k < stock[i].sequenceLength; k++)
{
sum += stock[i].prices[k];
if (sum >= stock[i].lowerBound && sum <= stock[i].upperBound)
count++;
}
}
if (stock[i].prices[stock[i].sequenceLength - 1] >= stock[i].lowerBound && stock[i].prices[stock[i].sequenceLength - 1] <= stock[i].upperBound)
count++;
stock[i].count = count;
count = 0;
}
Console.Clear();
for (int i = 0; i < stock.Length; i++)
Console.WriteLine(stock[i].count);
}
There's already an answer with O(N^2) complexity, I'll propose a O(NlogN) solution.
Create an array sums, where sums[0] = array[0] and sums[i] = sums[i-1]+array[i]. Now, for each index i in sums, you need to find number of indexes j such that sums[i] - sums[j] is in range [lower, upper]. But how to find number of indexes j?
Create a balanced binary search tree (AVL tree). Insert sums[0] in it. Start processing nodes from left to right. After processing a node, add it to the tree. You can search for the number of indexes in range [lower, upper] in O(logN) complexity, and same applies for the insertion as well. That will give you a total time complexity of O(NlogN).
If I understand the problem (and the jury is out)
The premise is, the first loop works its way across the array. The second loop is in charge of keeping a sum and checking the range, then yielding the result
Obviously this is O(n2) time complexity
Given
public static IEnumerable<int[]> GetSubs(int[] source, int lower, int upper)
{
for (var i = 0; i < source.Length; i++)
for (int j = i, sum = 0; j < source.Length; j++)
{
sum += source[j];
if (sum >= lower && sum <= upper)
yield return source[i..(j+1)];
}
}
Usage
var array = new[] { -5, -4, -3, -2, -1, 0, 2, 3, 4, 5, 6, 7, 8, 9 };
foreach (var sequence in GetSubs(array,2,5))
Console.WriteLine($"{sequence.Sum()} : [{string.Join(", ", sequence)}]");
Output
5 : [-5, -4, -3, -2, -1, 0, 2, 3, 4, 5, 6]
4 : [-4, -3, -2, -1, 0, 2, 3, 4, 5]
3 : [-3, -2, -1, 0, 2, 3, 4]
2 : [-2, -1, 0, 2, 3]
4 : [-1, 0, 2, 3]
2 : [0, 2]
5 : [0, 2, 3]
2 : [2]
5 : [2, 3]
3 : [3]
4 : [4]
5 : [5]
Full Demo Here
Note : You could probably do this in linq with Enumerable.Range, however this is pretty easy to understand
If you just wanted the count, you could remove the iterator all together, and just increment a counter when the if condition is true
public static int GetSubs(int[] source, int lower, int upper)
{
var result = 0;
for (var i = 0; i < source.Length; i++)
for (int j = i, sum = 0; j < source.Length; j++)
{
sum+= source[j];
if (sum >= lower && sum <= upper)
result++;
}
return result;
}
I have a list of numbers 1 and 0 only with fixed size of 25.
Example:
List<int>() { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
And I need to reorder or sort the list to:
Pattern A:
List<int>() { 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 };
or
Pattern B:
List<int>() { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 };
Max no of "1" in the list will always less than 13. The list will loop and search for nearest "1" and replace with current index if current index is "0" (either start from left or right only).
Here are my code snippets to produce both patterns above:
List SlotMapLP1 = new List() { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int i = 0, j = 0, k = 0, waferCount = 0, loopCtr = 0;
for (i = 0; i < SlotMapLP1.Count; i++ )
{
if (SlotMapLP1[i] == 1)
waferCount++;
}
List<int> ptnOne = new List<int>(SlotMapLP1);
List<int> ptnTwo = new List<int>(SlotMapLP1);
j = ptnOne.Count - 1;
while (j >= 0 && loopCtr <= waferCount) //list will start to traverse from right to left
{
if ((ptnOne[j] == 0 && (j + 1) % 2 > 0))
{
k = j - 1;
while (k >= 0)
{
if (ptnOne[k] == 1 && (ptnOne[k] != ptnOne[j]))
{
ExtensionMethods.Swap(ptnOne, k, j); //swap the two items
loopCtr++;
break;
}
k--;
}
}
else
{
if (j == 0 || j + 1 == ptnOne.Count) break;
if (ptnOne[j - 1] == 0 && ptnOne[j + 1] == 1)
{
k = j - 1;
while (k >= 0)
{
if (ptnOne[k] == 0 && (ptnOne[k] != ptnOne[j]))
{
ExtensionMethods.Swap(ptnOne, j, k); //swap the two items
loopCtr++;
break;
}
k--;
}
}
else
{
k = j - 1;
while (k >= 0)
{
if (ptnOne[k] == 1 && (ptnOne[k] != ptnOne[j]))
{
ExtensionMethods.Swap(ptnOne, j, k); //swap the two items
loopCtr++;
break;
}
k--;
}
}
}
j--;
}
loopCtr = 0; j = 0; k = 0;
while (j < ptnTwo.Count && loopCtr <= waferCount)//list will start to traverse from left to right
{
if (ptnTwo[j] == 0 && (j + 1) % 2 > 0)
{
k = j + 1;
while (k < ptnTwo.Count)
{
if (ptnTwo[k] == 1 && (ptnTwo[k] != ptnTwo[j]))
{
ExtensionMethods.Swap(ptnTwo, j, k); //swap the two items
loopCtr++;
break;
}
k++;
}
}
else
{
if (j == 0 || j + 1 == ptnOne.Count) break;
if (ptnTwo[j + 1] == 0 && ptnTwo[j - 1] == 1)
{
k = j + 1;
while (k < ptnTwo.Count)
{
if (ptnTwo[k] == 0 && (ptnTwo[k] != ptnTwo[j]))
{
ExtensionMethods.Swap(ptnTwo, j, k); //swap the two items
loopCtr++;
break;
}
k++;
}
}
else
{
k = j + 1;
while (k < ptnTwo.Count)
{
if (ptnTwo[k] == 1 && (ptnTwo[k] != ptnTwo[j]))
{
ExtensionMethods.Swap(ptnTwo, j, k); //swap the two items
loopCtr++;
break;
}
k++;
}
}
}
j++;
}
However, I do face some problem. Not all list input can be sorted or reorder to alternately if I use this method.
Are there better way or method to perform this type of sorting?
There's a solution that doesn't involve swapping elements in the list. You only have to figure out the pattern.
If there is only one 1:
1000000000000000000000000
There's a "1" followed by 24 zeros.
If there are 2 ones:
1010000000000000000000000
There's a "101" pattern followed by 22 zeros.
See where I'm getting at?
For 3 ones:
1010100000000000000000000
There's a "10101" pattern followed by 20 zeros.
So you only have to count the number of ones and build your pattern from there. The algorithm then becomes:
Let n = number of ones in the list
If there are no ones, both patterns A and B is just 25 zeros.
Else build alternating pattern of length n * 2 - 1.
For pattern A, concatenate 25 - (n * 2 - 1) zeros and the alternating pattern.
For pattern B, concatenate the alternating pattern and 25 - (n * 2 - 1) zeros. (Or the reverse of pattern A)
if the size is actually fixed to 25 items I think that it is easier to count the amount of 1 and build a new list according to that amount.
I have test with Pattern A and Pattern B but it will make my codes become longer due to multiple checking required. I created new pattern which I test so far is the best for my application which require movement of hardware. Just to share my idea.
Pattern C :
List() { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
Here are the code portion:
List<int> SlotMapLP1 = new List<int>();
for (int x = 0; x < 25; x++)
{
SlotMapLP1.Add(int.Parse(waferArrangement.Substring(x, 1))); //input string contains 1 and 0; where 1 should be max 12 count only
}
int i = 0, j = 0, k = 0, waferCount = 0;
for (i = 0; i < SlotMapLP1.Count; i++ )
if (SlotMapLP1[i] == 1)
waferCount++;
List<int> ptnOne = new List<int>(SlotMapLP1);
for (j = 0; j < ptnOne.Count; j++ )
{
if(j == 0 || j % 2 == 0)
{
if (ptnOne[j] == 1)
{
k = j + 1;
while (k < ptnOne.Count())
{
if (ptnOne[k] == 0)
{
ExtensionMethods.Swap(ptnOne, k, j); //swap position
break;
}
k++;
}
}
}
else
{
if (ptnOne[j] == 0)
{
k = j + 1;
while (k < ptnOne.Count())
{
if (ptnOne[k] == 1)
{
ExtensionMethods.Swap(ptnOne, k, j); //swap position
break;
}
k++;
}
}
}
}
I tested with several inputs and the sorting/reorder function works well.
i am searching for an algorithm that can find the the biggest Areas in a Grid.
if i have something like this:
Red Blocks = Blocks with Collision
i have to check 28 collision Objekts.
I need an algorithm that can find this:
now i only have to check 5 Objekts.
Is there an easy c# algorithm for that?
If you wanted the absolute minimum number of rectangles, then I would suggest this answer to you. Since you want easy, though, here's my suggestion, which is 2-competitive with the minimum. First, by scanning the rows one by one, find the minimum exact cover with rectangles only one row high.
00000000
1 2
3 44 5
6 77 8
99999999
Now for each pair of adjacent rows in turn, try to merge their rectangles. Assuming that they are sorted by horizontal position, then the loop looks like a sorted merge.
00000000
--------
1 2
No merges possible.
1 2
--------
3 44 5
Merge 1, 3 and 2, 5.
1 2
1 44 2
--------
6 77 8
Merge 1, 6 and 4, 7 and 2, 8.
1 2
1 44 2
1 44 2
--------
99999999
No merges possible. The final result is the following.
00000000
1 2
1 44 2
1 44 2
99999999
here is a solution for Unity
using UnityEngine;
using System.Collections;
public class CollisionTileMerger:MonoBehaviour{
ArrayList rects = new ArrayList();
public int[,] rowCheck(int[,]array)
{
int y = array.GetLength(0);
int x = array.Length /y ;
int count = 1;
ArrayList rec = new ArrayList ();
for(int i=0; i< y ;i++){
for(int j=0; j< x ;j++)
{
if(array[i,j] == -1)
{
array[i,j] = count;
rec.Add(i);
rec.Add(j);
}
else
{
if(rec.Count>0)
{
rects.Add (rec);
rec = new ArrayList();
count++;
}
}
}
if(rec.Count>0)
{
rects.Add (rec);
rec = new ArrayList();
count++;
}
}
return array;
}
public int[,] Merger(int[,]array)
{
int y = array.GetLength(0);
int x = array.Length /y ;
int[,] coppy = (int[,])array.Clone ();
for (int i=0; i< y-1; i++)
{
int row = i;
for (int j=0; j< x; j++)
{
if(coppy[row,j]>0&&coppy[row+1,j]>0)
{
if(j==0)
{
coppy[row+1,j] = coppy[row,j];
}
else
{
if((coppy[row,j-1]>0&&coppy[row+1,j-1]>0)||(coppy[row,j-1]==0&&coppy[row+1,j-1]==0))
{
coppy[row+1,j] = coppy[row,j];
if(j==x-1)
{
//letzte Zeile
//speichern
array = (int[,])coppy.Clone ();
}
}
else
{
//zurücksetzen
coppy = (int[,])array.Clone ();
}
}
}
else if(coppy[row,j]==0&&coppy[row+1,j]==0)
{
//speichern
array = (int[,])coppy.Clone ();
}
else
{
//zurücksetzen
coppy = (int[,])array.Clone ();
}
}
}
//speichern
array = (int[,])coppy.Clone ();
return array;
}
// Use this for initialization
void Start () {
int[,] a = new int[,] {
{-1,-1,-1,-1,-1,-1,-1,-1},
{-1, 0, 0, 0, 0, 0, 0,-1},
{-1, 0, 0, -1, 0, 0, 0,-1},
{-1, 0, 0, -1, 0, 0, 0,-1},
{-1, 0, 0, -1, 0, 0, 0,-1},
{-1, 0, 0,-1,-1, 0, 0,-1},
{-1, 0, 0,-1,-1, 0, 0,-1},
{-1, 0, 0,-1,-1, 0, 0,-1},
{-1,-1,-1,-1,-1,-1,-1,-1}};
displayArray (Merger(rowCheck (a)));
}
// Update is called once per frame
void Update () {
}
public void displayArray(int[,]array)
{
int y = array.GetLength(0);
int x = array.Length /y ;
string row="";
for (int i = 0; i< y; i++)
{
for(int j = 0; j<x;j++)
{
row+= array[i,j]+" ";
}
row+= "\r\n";
}
Debug.Log(row);
/*foreach( int a in array )
{
Debug.Log( array.GetLength(0) );
Debug.Log( array.Length );
}*/
}
}
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();
}
}