Converting Codility solution to C# (Grocery-store, Hydrogenium 2013) - c#

In order to learn and understand how Dijkstra's algorithm is used to solve the "Grocery Store" ([Hydrogenium 2013]: https://codility.com/programmers/challenges/hydrogenium2013) problem on codility, I'm trying to rewrite the #2, O(n^2) solution(https://codility.com/media/train/solution-grocery-store.pdf) in C#.
1) What language are those solutions written in?
2) What would be the C# equivalent to this bit of code?
G = [[]] *N
for i in xrange(M):
G[A[i]] = G[A[i]] + [(B[i], C[i])]
G[B[i]] = G[B[i]] + [(A[i], C[i])]
This is what I have so far
int[] G = new int[N];
for (int i = 0; i < M; i++)
{
G[A[i]] = G[A[i]];
G[B[i]] = G[B[i]];
}
Thanks in advance,
Gregory

Downloaded IDLE (a python IDE...kind of) and figured it out. It appears to be adding pairs to each array element. Here's the code I came up with if anyone else happens to stumble across the same problem.
private struct nodePair
{
public int node;
public int time;
public nodePair(int node, int time)
{
this.node = node;
this.time = time;
}
}
public int solution(int[] A, int[] B, int[] C, int[] D)
{
int M = A.Length;
int N = D.Length;
//build the graph
List<nodePair>[] G = new List<nodePair>[N];
for (int i = 0; i < N; i++)
{
G[i] = new List<nodePair>();
}
for (int i = 0; i < M; i++)
{
G[A[i]].Add(new nodePair(B[i], C[i]));
G[B[i]].Add(new nodePair(A[i], C[i]));
}
//initialize the distance table
int[] dist = new int[N];
for (int i = 0; i < N; i++)
{
dist[i] = int.MaxValue;
}
bool[] visited = new bool[N];
for (int i = 0; i < N; i++)
{
visited[i] = false;
}
//look for the minimum value
int ii = 0; ;
dist[0] = 0;
for (int k = 0; k < N; k++)
{
int s = int.MaxValue;
//find the minimum
for (int j = 0; j < N; j++)
{
if ((dist[j] < s) && (visited[j] == false))
{
s = dist[j];
ii = j;
}
}
visited[ii] = true;
if (s < D[ii])
{
return s;
}
List<nodePair> thisNodeLIst = G[ii];
foreach (nodePair oneNode in thisNodeLIst)
{
dist[oneNode.node] = Math.Min(dist[oneNode.node], s + oneNode.time);
}
}//for
return -1;
}
}

Related

I got a stack overflow error and I can't figure out what causes it

I am trying to generate a maze and I faced a stack overflow error while trying to do divide and conquer kind of approach to my 2D array.I will have to post the whole code since I have no idea what causes it and i am very inexperienced in the subject.
this is the details : System.StackOverflowException
HResult=0x800703E9
Message=
this is where the exception happens
!https://imgur.com/a/iwX8pKY
https://www.robinsnyder.com/MazeStaticGif I got the idea from here.
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;
namespace labirentVize2
{
class labirentOlustur
{ public static int delik;
public static int x=0;
public static int y;
public static int N = 30;
public static int boy = 30;
int[,] uret = new int[N, N];
public Array girisCikis(int[,] uret)
{
int en1=1;
Random giris = new Random();
int gir = giris.Next(1, 29);
if (gir > 14)
{
int gir2 = giris.Next(15, 28);
int gir3 = (gir + gir2)/2;
uret[0, gir] = 1;
uret[0, gir2] = 1;
uret[0, gir3] = 1;
}
else
{
int gir2 = giris.Next(1, 15);
int gir3 = (gir + gir2)/2;
uret[0, gir] = 1;
uret[0, gir2] = 1;
uret[0, gir3] = 1;
}
Random cikis = new Random();
int cik = cikis.Next(1, 28);
if (cik > 14)
{
int cik2 = cikis.Next(1, 28);
int cik3 = (cik + cik2)/2;
uret[29, cik] = 1;
uret[29, cik2] = 1;
uret[29, cik3] = 1;
}
else
{
int cik2 = cikis.Next(15, 28);
int cik3 = (cik + cik2)/2;
uret[29, cik] = 1;
uret[29, cik2] = 1;
uret[29, cik3] = 1;
}
labYap(uret, en1, x, boy);
return uret;
}
void labGoster(int[,] uret)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
Console.Write(" " + uret[i, j] + " ");
Console.WriteLine();
}
}
public void labYap(int[,] uret, int en1, int x, int boy)
{
int total1 = 0;
Random rand2 = new Random();
for (int i = 0; i < uret.GetLength(0); i++)
{
for (int j = 0; j < uret.GetLength(1); j++)
{
total1 += uret[i, j];}
}
if(total1 > 800)
{
labGoster(uret);
}
else if (total1 == 784)
{
Random rand1 = new Random();
en1 = rand1.Next(2, 29);
x = 30;
delik = rand2.Next(1, 29);
}
else
{
Random rand = new Random();
en1 = rand.Next(1, en1);
boy = boy - en1;
delik = rand2.Next(1, en1);
}
if (diziUstToplam(uret, en1) >= diziAltToplam(uret, en1))
{
y = en1;
for (int j = 0; j < x ; j++)
{
uret[en1, j] = 0;
}
uret[en1, delik] = 1;
labYap(uret, en1, x, boy);
labYap(uret, boy, x, boy);
}
else
{ x = en1;
for (int j = 0; j < en1; j++)
{
uret[j, en1] = 0;
}
uret[delik, en1] = 1;
labYap(uret, en1, x, boy);
labYap(uret, en1, x, boy);
}
int diziUstToplam(int[,] uret, int en1)
{
int total = 0;
// Dizinin ilk boyutu için
for (int i = 0; i < en1; i++)
{
// Dizinin ikinci boyutu için
for (int j = 0; j < uret.GetLength(1); j++)
{
total += uret[i, j];
}
}
return total;
}
int diziAltToplam(int[,] uret, int en1)
{
int total = 0;
// Dizinin ilk boyutu için
for (int i = en1; i < 30; i++)
{
// Dizinin ikinci boyutu için
for (int j = 0; j < uret.GetLength(1); j++)
{
total += uret[i, j];
}
}
return total;
}
int rastgeleSayi()
{
Random rand = new Random();
int en1 = rand.Next(1, 29);
return en1;
}
}
}
}
The stack overflow error is because you call labYear() too many times from within itself. You need to ensure that you have some escape condition where the function can return.
See more here: https://learn.microsoft.com/en-us/dotnet/api/system.stackoverflowexception?view=net-6.0

How to Break a For Loop From an If Statement Inside the Loop (C#)

I am working on an A* Pathfinding method that uses a custom class instead of nodes, but am having issues with my loops. The first for loop using int i is able to go up to 3 (Player1.instance.movement = 3), but I need to use an if statement inside of that loop to check if the target position has already been found. I am wondering if it is possible to break my for loop when my If statement is false.
public void GetNeighbors(Tile originTile)
{
Tile originalTile = originTile;
nextTile.Clear();
int minX = 0;
int minY = 0;
var originCostFunc = Mathf.Infinity;
for (int i = 0; i < Player1.instance.movement; i++)
{
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (x != y && y != x)
{
var costX = Mathf.Abs((originTile.transform.position.x + x) - originalTile.transform.position.x);
var costY = Mathf.Abs((originTile.transform.position.y + y) - originalTile.transform.position.y);
var distanceX = Mathf.Abs(targetPos.transform.position.x - (originTile.transform.position.x + x));
var distanceY = Mathf.Abs(targetPos.transform.position.y - (originTile.transform.position.y + y));
var costFunc = costX + costY + distanceX + distanceY;
if (costFunc <= originCostFunc)
{
originCostFunc = costFunc;
minX = x;
minY = y;
Debug.Log($"x: {x}, y: {y}");
}
}
}
}
nextTile.Add(GridManagerHandPlaced.instance.GetTileAtPosition(new Vector2(originTile.transform.position.x + minX, originTile.transform.position.y + minY)));
if (nextTile[i] != targetPos)
{
originTile = nextTile[i];
}
else
{
break;
}
}
DisplayPath();
}
You can break loop several times by condition.
bool breakLoop = false;
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
for (int k = 0; k < length; k++)
{
breakLoop = nextTile == target;
if (breakLoop)
break;
}
if (breakLoop)
break;
}
if (breakLoop)
break;
}
Or move search logic to separated method and return a value from any number of nested loops
string path = FindPath();
Display(path);
string FindPath()
{
for (int i = 0; i < length; i++)
{
for (int j = 0; j < length; j++)
{
for (int k = 0; k < length; k++)
{
if (nextTile == target)
return nextTile;
}
}
}
return null;
}
Never use goto operator.
This is one of the few valid cases where I'd use goto. In-fact, this is the example given in the docs for when it should be used.
void CheckMatrices(Dictionary<string, int[][]> matrixLookup, int target)
{
foreach (var (key, matrix) in matrixLookup)
{
for (int row = 0; row < matrix.Length; row++)
{
for (int col = 0; col < matrix[row].Length; col++)
{
if (matrix[row][col] == target)
{
goto Found;
}
}
}
Console.WriteLine($"Not found {target} in matrix {key}.");
continue;
Found:
Console.WriteLine($"Found {target} in matrix {key}.");
}
}
Note the syntax for the label is simply myLabel: and you can place it anywhere in procedurally executable code.
For sake of covering other ways of handling this situation, here is the boolean solution.
bool breakLoops = false;
for (int i = 0; i < length1; i++)
{
for (int ii = 0; ii < length2; ii++)
{
for (int iii = 0; iii < length3; iii++)
{
if (breakingCondition)
{
breakLoops = true;
break;
}
}
if (breakLoops) break;
}
if (breakLoops) break;
}
Simple and straightforward, but requires a break condition check at the end of each loop that you want to break out of.

Converting this MatLab iterating code to C#. Outputs from matlab and c# are different

I am trying to convert this code:
function [C] = cumulativeMaxV2(A)
cols = size(A,2);
bscans = size(A,3);
C = zeros(size(A));
for col = 1:cols
for bscan = 1:bscans
aline = A(:,col,bscan);
for i = 1:length(aline)
if i == 1
C(i,col,bscan)=0;
else
C(i,col,bscan) = max(A(1:i-1, col,bscan));
end
end
end
end
My C# code is below:
static double[,,] CumulativeMax(double[,,] A)
{
int cols = 304; //A.GetLength(1);
int bscans = 304; //A.GetLength(2);
double[,,] C = new double[160, 304, 304];
Console.Write("Processing... ");
using (var progress = new ProgressBar())
{
for (int col = 0; col < cols; col++)
{
for (int bscan = 0; bscan < bscans; bscan++)
{
double[] aline = new double[160];
for (int i = 0; i < 160; i++)
aline[i] = A[i,col,bscan];
for (int i = 0; i < aline.GetLength(0); i++)
{
if (i == 0)
C[i,col,bscan] = 0d;
else if (i == 1)
{
double[] temp = new double[i];
for (int x = 0; x < i; x++)
temp[x] = A[x,col,bscan];
C[i,col,bscan] = temp.Max();
}
else
{
double[] temp = new double[i - 1];
for (int x = 0; x < i - 1; x++)
temp[x] = A[x,col,bscan];
C[i,col,bscan] = temp.Max();
}
}
}
progress.Report((double)col/cols);
}
}
Console.WriteLine("Done.");
return C;
}
Outputs from MatLab do not match those from the C# code.
Any pointers to where the bugs are in my C# code would be great. I'm not very good with MatLab.
I think this may be due to how MatLab's max function deals with infinity and NaNs.

Genetic algorithm - clustering points on screen

Below is the code I wrote for clustering using genetic algorithm. Points are from a picturebox, generated randomly (X,Y) before calling this class. However, the result of this algorithm is much worse than k-means or lbg I'm comparing it to. Can someone take a look for any errors in the algorithm, maybe I omitted something. Thanks.
I did this using arrays, the 2 other I did using lists, but I don't think that should have any impact on result.
public class geneticAlgorithm
{
static int pom = 0;
static PictureBox pb1;
public geneticAlgorithm(PictureBox pb)
{
pb1 = pb;
}
public static void doGA(PointCollection points, int clusterCounter)
//points is a list of points,
//those point have (X,Y) coordinates generated randomly from pictureBox
//coordinates. clusterCounter is how many clusters I want to divide the points into
{
//this part converts list of points into array testtab,
//where each array field hold X,Y of a point
Point[] test = new Point[points.Count];
test = points.ToArray();
double[][] testtab = new double[test.Length][];
for (int i = 0; i < testtab.GetLength(0); i++)
{
testtab[i] = new double[2];
testtab[i][0] = test[i].X;
testtab[i][1] = test[i].Y;
}
//end of converting
int n = testtab.GetLength(0);
int k = clusterCounter;
int chromosomeCount = 500;
int dimensions = 2;
double[][] testClusters = new double[k][];
for (int i = 0; i < k; i++)
{
testClusters[i] = new double[dimensions];
}
double[][] testChromosomes = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
testChromosomes[i] = new double[2 * k];
}
int[][] testChromosomesInt = new int[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
testChromosomesInt[i] = new int[2 * k];
}
double[] partner = new double[chromosomeCount];
double[][] roulette = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
roulette[i] = new double[1];
}
double[][] errors = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
errors[i] = new double[1];
}
double crossingPossibility = 0.01;
double mutationPossibility = 0.0001;
int maxIterations = 10000;
//here I create chromosomes and initial clusters
for (int j = 0; j < chromosomeCount; j++)
{
for (int i = 0; i < k; i++)
{
Random rnd = new Random();
int r = rnd.Next(n);
for (int q = 0; q < dimensions; q++)
{
testClusters[i][q] = testtab[r][q];
}
}
int help = 0;
for (int i = 0; i < k; i++)
for (int l = 0; l < dimensions; l++) // here is creation of chromosome
{
testChromosomes[j][help] = testClusters[i][l];
help++;
}
//end
//here I call accomodation function to see which of them are good
errors[j][0] = accomodationFunction(testClusters, testtab, n, k);
//end
//cleaning of the cluster table
testClusters = new double[k][];
for (int i = 0; i < k; i++)
{
testClusters[i] = new double[dimensions];
}
}
//end
for (int counter = 0; counter < maxIterations; counter++)
{
//start of the roulette
double s = 0.0;
for (int i = 0; i < chromosomeCount; i++)
s += errors[i][0];
for (int i = 0; i < chromosomeCount; i++)
errors[i][0] = chromosomeCount * errors[i][0] / s;
int idx = 0;
for (int i = 0; i < chromosomeCount; i++)
for (int j = 0; i < errors[i][0] && idx < chromosomeCount; j++)
{
roulette[idx++][0] = i;
}
double[][] newTab = new double[chromosomeCount][];
for (int i = 0; i < chromosomeCount; i++)
{
newTab[i] = new double[2 * k];
}
Random rnd = new Random();
for (int i = 0; i < chromosomeCount; i++)
{
int q = rnd.Next(chromosomeCount);
newTab[i] = testChromosomes[(int)roulette[q][0]];
}
testChromosomes = newTab;
//end of roulette
//start of crossing chromosomes
for (int i = 0; i < chromosomeCount; i++)
partner[i] = (rnd.NextDouble() < crossingPossibility + 1) ? rnd.Next(chromosomeCount) : -1;
for (int i = 0; i < chromosomeCount; i++)
if (partner[i] != -1)
testChromosomes[i] = crossing(testChromosomes[i], testChromosomes[(int)partner[i]], rnd.Next(2 * k), k);
//end of crossing
//converting double to int
for (int i = 0; i < chromosomeCount; i++)
for (int j = 0; j < 2 * k; j++)
testChromosomes[i][j] = (int)Math.Round(testChromosomes[i][j]);
//end of conversion
//start of mutation
for (int i = 0; i < chromosomeCount; i++)
if (rnd.NextDouble() < mutationPossibility + 1)
testChromosomesInt[i] = mutation(testChromosomesInt[i], rnd.Next(k * 2), rnd.Next(10));
//end of mutation
}
//painting of the found centre on the picture box
int centrum = max(errors, chromosomeCount);
Graphics g = pb1.CreateGraphics();
SolidBrush brush = new SolidBrush(Color.Red);
for (int i = 0; i < 2 * k - 1; i += 2)
{
g.FillRectangle(brush, testChromosomesInt[centrum][i], testChromosomesInt[centrum][i + 1], 20, 20);
}
return;
}
//end of painting
public static int max(double[][] tab, int chromosomeCount)
{
double max = 0;
int k = 0;
for (int i = 0; i < chromosomeCount; i++)
{
if (max < tab[i][0])
{
max = tab[i][0];
k = i;
}
}
return k;
}
public static int[] mutation(int[] tab, int elem, int bit)
{
int mask = 1;
mask <<= bit;
tab[elem] = tab[elem] ^ mask;
return tab;
}
public static double[] crossing(double[] tab, double[] tab2, int p, int k)
{
double[] hold = new double[2 * k];
for (int i = 0; i < p; i++)
hold[i] = tab[i];
for (int i = p; i < 2 * k; i++)
hold[i] = tab2[i];
return hold;
}
//accomodation function, checks to which centre which point belongs based on distance
private static double accomodationFunction(double[][] klastry, double[][] testtab, int n, int k)
{
double Error = 0;
for (int i = 0; i < n; i++)
{
double min = 0;
int ktory = 0;
for (int j = 0; j < k; j++)
{
double dist = distance(klastry[j], testtab[i]);
if (j == 0)
{
min = dist;
}
if (min > dist)
{
min = dist;
ktory = j;
}
}
Error += min;
}
pom++;
return 1 / Error;
}
public static double distance(double[] tab, double[] tab2)
{
double dist = 0.0;
for (int i = 0; i < tab.GetLength(0); i++)
dist += Math.Pow(tab[i] - tab2[i], 2);
return dist;
}
}
The algorithm should work like so: (excuse me if not the best english)
1. Get random points (let's say 100)
2. Check into how many clusters we want to split them (the same thing I would do using k-means for example
3. Get starting population of chromosomes
4. Throu cutting on the roulette, crossing and mutation pick the best x centres, where x is the amount of clusters we want
5. Paint them.
Here are some results, and why I think it's wrong: (it's using 100 points, 5 clusters)
k-means:
lbg:
genetic(without colors now):
I hope this clarifies a bit.

c# parallel.for gaussian elimination

I am trying to solve Gaussian elimination in c# using parallel-processing (in this case Parallel.For). My code is sometimes running fine and sometimes not.
I used as a starting point the code shown on the link: http://www.codeproject.com/Tips/388179/Linear-Equation-Solver-Gaussian-Elimination-Csharp .
I didn't use Parallel.For for back insertion just yet because there is problem with elimination.
Elimination Class:
public static bool Gauss(double[][] M)
{
int rowCount = (M.GetLength(0));
int temp = rowCount - 1;
//elimination
Parallel.For(0, temp, sourceRow =>
//for (int sourceRow = 0; sourceRow + 1 < rowCount; sourceRow++)//diagonal
{
for (int destRow = sourceRow + 1; destRow < rowCount; destRow++)//destination row
{
double df = M[sourceRow][sourceRow];
double sf = M[destRow][sourceRow];
for (int j = 0; j < rowCount + 1; j++) // line
{
M[destRow][j] = (M[destRow][j] * df - M[sourceRow][j] * sf) / df;
}
}
});
//back-insertion
for (int row = rowCount - 1; row >= 0; row--)
{
double f = M[row][row];
if (f == 0) return false;
for (int i = 0; i < rowCount + 1; i++) M[row][i] /= f;
for (int destRow = 0; destRow < row; destRow++)
{
M[destRow][rowCount] -= M[destRow][row] * M[row][rowCount];
M[destRow][row] = 0;
}
}
return true;
}
Generate Array:
public static double[][] GenerateArray2(int n)
{
Random rnd = new Random();
double[][] M = new double[n][];
for (int i = 0; i < n; i++)
{
M[i] = new double[n + 1]; // Create inner array
for (int j = 0; j < n + 1; j++)
M[i][j] = rnd.Next(-20, 20);
}
return M;
}
Print Array
public static string Print2(double[][] M)
{
string str = "";
int rowCount = M.GetUpperBound(0) + 1;
for (int row = 0; row < rowCount; row++)
{
for (int i = 0; i <= rowCount; i++)
{
str += M[row][i];
str += "\t";
}
str += Environment.NewLine;
}
return str;
}
Results are wrong in matrix 16x17 and up. At this point I don't know how to continue, I tried to lock M in elimination, didn't help.
Thanks for any help.

Categories

Resources