I have a method that is an "Improved version of Selection Sort". However, the code is not running as " temp[x] = 0;" this line gives an out of bounds of the array error. I do not want to use an ArrayList. How would I change this line to be in bounds of the array?
public static void ImprovedSelectionSort(int[] Array)
{
Stopwatch timer = new Stopwatch();
timer.Start();
int[] temp = new int[Array.Length];
for (int x = 1; x <= Array.Length; x++)
{
//OtherList.Add(0); -- what I want to do
temp[x] = 0;
}
int n = Array.Length;
int i = 0;
while (i < n)
{
int rear = 0;
int curMax = Array[i];
temp[rear] = i;
int j = i + 1;
while (j < n)
{
if (curMax < Array[j])
{
curMax = Array[j];
rear = -1;
}
if (curMax == Array[j])
{
rear = rear + 1;
temp[rear] = j;
}
j++;
}
int front = 0;
int p = Array[temp[front]];
while (front <= rear)
{
int temporary = p;
Array[temp[front]] = Array[i];
Array[i] = temporary;
i++;
front += 1;
}
}
for (int x = 1; x <= Array.Length; x++)
This is most likely the issue. The last index in an array is the length minus 1 (so, a 52-card deck goes from 0..51). Changing the "x <= Array.Length" component to "x < Array.Length" should fix the issue.
Change the <= to < in the for loop. This is a common mistake among novice devs, and not something you should sweat. But it's a good thing to keep in mind for the future.
Related
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.
So I wrote bucket sort implementation (I use rnd.NextDouble() to fill my array, so all the elements are in the range between 0 and 1). And I have number of experiments (10 experiments for each array size) and different array sizes (I start with 1000 and then +1000, etc. till 300.000). And sometimes it works fine, but sometimes it gives me OutOfRange exception:
public static void BucketSortImplement(ref int countOfElements, ref float[] array)
{
List<float>[] buckets = new List<float>[countOfElements];
for (int i = 0; i < countOfElements; i++)
{
buckets[i] = new List<float>();
}
for (int i = 0; i < countOfElements; i++)
{
float indexOfElement = array[i] * countOfElements;
buckets[(int)indexOfElement].Add(array[i]); // right here
}
for (int i = 0; i < countOfElements; i++)
{
for (int j = 0; j < buckets[i].Count; j++)
{
float keyElement = buckets[i][j];
int k = j - 1;
while (k >= 0 && buckets[i][k] > keyElement)
{
buckets[i][k + 1] = buckets[i][k];
k -= 1;
}
buckets[i][k + 1] = keyElement;
}
}
int arrayIndex = 0;
for (int i = 0; i < countOfElements; i++)
{
for (int j = 0; j < buckets[i].Count; j++)
{
array[arrayIndex++] = buckets[i][j];
}
}
}
I am a bit confused, because the algorithm itself looks fine, that is I have to calculate array[i] * countOfElements to get the index where I can put my element. Could you please direct me?
If you array contain value '1' it will lead to OutOfRange, because if you have a size of the list equal to 3 (for example) then valid indexes will be in the range [0, 2].
I have to write a program that creates a two dimensional array and fills it like a snake. Here is the task itself:
Blockquote write a program that creates a two-dimensional numeric array and this array is filled with a "snake": first the first row (from left to right), then the last column (from top to bottom), the last row (from right to left), the first column (from bottom to top), the second row ( left to right), etc.
I tried to write something, but bugs constantly appear. Please help to shorten this code and make it correct.
class Program
{
static void Main(string[] args)
{
Random rand = new Random();
int len = rand.Next(5, 20);
int wid = rand.Next(5, 20);
int[,] arr = new int[len, wid];
int num = 10;
int line = 0;
int line2 = len;
int col = wid - 1;
int col2 = 0;
for (int i = 0; i <= (len > wid ? len : wid); i++)
{
for (int k = 0; k < wid; k++, num++)
{
arr[line, k] = num;
}
line++;
for (int k = 0; k < len; k++, num++)
{
arr[k, col] = num;
}
col++;
for (int k = (wid - 1); k >= 0; k--, num++)
{
arr[line2, k] = num;
}
line2++;
for (int k = 0; k < (len - 1); k++, num++)
{
arr[k, col2] = num;
}
col2++;
}
for (int i = 0; i <= len; i++)
for (int q = 0; q <= wid; q++)
{
Console.WriteLine(arr[i, q] + " ");
}
}
}
I've read the CLRS and tried to implement the recursive merge sort algorithm . cant see what the error is but everytime i run it gives me an "Index out of bounds error "
i've been trying for 5h now
static public void MergeSort(int[] input, int IndexStanga, int IndexDreapta)
{
if (IndexStanga < IndexDreapta)
{
int IndexMijloc = (IndexDreapta + IndexStanga) / 2;
MergeSort(input, IndexStanga, IndexMijloc);
MergeSort(input, IndexMijloc + 1, IndexDreapta);
Merge(input, IndexStanga, IndexDreapta, IndexMijloc);
}
}
static public void Merge(int[] input, int stanga, int dreapta, int mijloc)
{
int lungDR = 0;
int lunST = 0;
lungDR = dreapta - mijloc;
lunST = mijloc - stanga + 1;
int[] valDreapta = new int[lungDR + 1];
int[] valStanga = new int[lunST + 1];
valDreapta[valDreapta.Length - 1] = int.MaxValue;
valStanga[valStanga.Length - 1] = int.MaxValue;
int i = 0;
int j = 0;
for (i = stanga; i <= mijloc; i++) valStanga[i] = input[i];
for (i = 0; i < lungDR; i++) { valDreapta[i] = input[i + mijloc + 1]; }
i = 0;
j = 0;
for (int k = 0; k < input.Length; k++)
{
if (valStanga[i] <= valDreapta[j]) //error out of bounds
{
input[k] = valStanga[i];
i++;
}
else
{
input[k] = valDreapta[j];
j++;
}
}
}
Fixes noted in comments below. First fix for moving data from input to valStanga. Second fix for the range on merging back to input. The parameters for merge are in an unusual order, first, last, middle. Normally the order is first, middle, last.
Comments: The program will have issues if the array to be sorted contains elements equal to max integer. It would be more efficient to do a one time allocation of a working array, rather than allocate new sub-arrays on every call to merge. The copy operations can be avoided by changing the direction of merge with each level of recursion.
int i = 0;
int j = 0;
for (i = 0; i < lungDR; i++) { valDreapta[i] = input[i + mijloc + 1]; }
for (i = 0; i < lunST; i++) { valStanga[i] = input[i + stanga]; } // fix
i = 0;
j = 0;
for (int k = stanga; k <= dreapta; k++) // fix
{
if (valStanga[i] <= valDreapta[j])
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.