Reverse order of bubble sort of null elements - c#

I'm trying to reverse my bubble sort so all null elements are pushed to the end of array instead of the beginning as they're getting sorted now. Any advice on how this can be achieved?
for (int outerLoop = 0; outerLoop < students.Length-1; outerLoop++)
{
for (int innerLoop = 0; innerLoop < students.Length-1; innerLoop++)
{
if (students[outerLoop+1] == null)
{
var tempObject = students[outerLoop+1];
students[outerLoop+1] = students[innerLoop];
students[innerLoop] = tempObject;
}
}
}

Corrected code:
for (int outerLoop = 0; outerLoop < students.Length-1; outerLoop++)
{
for (int innerLoop = 0; innerLoop < students.Length-1; innerLoop++)
{
if (students[innerLoop] == null)
{
var tempObject = students[innerLoop+1];
students[innerLoop+1] = students[innerLoop];
students[innerLoop] = tempObject;
}
}
}
This will not sort your array but only drop the nulls at the bottom.
In fact you can do away with the temp variable:
for (int outerLoop = 0; outerLoop < students.Length-1; outerLoop++)
{
for (int innerLoop = 0; innerLoop < students.Length-1; innerLoop++)
{
if (students[innerLoop] == null)
{
students[innerLoop] = students[innerLoop+1];
students[innerLoop+1] = null;
}
}
}
Note:
C# 7 introduced tuples which enables swapping two variables without a temporary one:
int a = 10;
int b = 2;
(a, b) = (b, a);
This assigns b to a and a to b.

Try following. You have to test for outer being null and inner not being null :
for (int outerLoop = 0; outerLoop < students.Length - 1; outerLoop++)
{
for (int innerLoop = outerLoop + 1; innerLoop < students.Length; innerLoop++)
{
if ((students[outerLoop] == null) && (students[innerLoop] != null))
{
var tempObject = students[outerLoop];
students[outerLoop] = students[innerLoop];
students[innerLoop] = tempObject;
}
}
}

There's a faster, easier and stable approach with O(n) time complexity:
int at = 0;
for (int i = 0; i < students.Length; ++i)
if (students[i] != null)
students[at++] = students[i];
for (int i = at; i < students.Length; ++i)
students[i] = null;
However, if you insist on bubble sort: we can implement it in a bit different way
for (bool wrongOrder = true; wrongOrder;) {
wrongOrder = false;
for (int i = 1; i < students.Length; i++) {
if (students[i - 1] == null && students[i] != null) {
// At least 2 items has wrong order, swap them
var temp = students[i - 1];
students[i - 1] = students[i];
students[i] = temp;
wrongOrder = true;
}
}
}

Related

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.

Repeating 2 methods to make into 1 method

I have this repeating code , and I'm unsure of how I can make it in only 1 method.
public int isWonVertical()
{
for (int i = 0; i < columns; i++)
{
resetCounter();
for (int j = 0; j < rows; j++)
{
if (raster[j, i] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[j, i] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}//isWonVertical
public int isWonHorizontal()
{
for (int i = 0; i < rows; i++)
{
resetCounter();
for (int j = 0; j < columns; j++)
{
if (raster[i, j] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[i, j] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}//isWonHorizontal
The returns and resetCounter() I can all put in 1 method. But how do I make sure the for loops are different for vertical/horizontal. I assume it's with giving parameters with, and then checking wether I gave 'vertical' or 'horizontal' as a paramter. But i'm unsure how to make this actually work.
Thank you.
public int isWon(DirectionEnum enum)
{
int counter1 = enum == DirectionEnum.IsVertical ? columns : rows;
int counter2 = enum == DirectionEnum.IsHorizontal ? columns: rows;
for (int i = 0; i < counter1 ; i++)
{
resetCounter();
for (int j = 0; j < counter2; j++)
{
if (raster[i, j] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[i, j] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}
How about his, two parameters, one for the inner array, one for the outer. Then your client (calling code) needs to decide what to use as inner or outer, either rows or columns
public int isWon(outerArray, innerArray)
{
for (int i = 0; i < outerArray; i++)
{
resetCounter();
for (int j = 0; j < innerArray; j++)
{
if (raster[i, j] == 1) counterPlayer1++;
else counterPlayer1 = 0;
if (raster[i, j] == 2) counterPlayer2++;
else counterPlayer2 = 0;
if (counterPlayer1 == tokenStreak) return 1;
if (counterPlayer2 == tokenStreak) return 2;
}
}
return 0;
}

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

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;
}
}

Insertion Sorting c#

Can you guys please help me with basic insertion sorting in C#. I have a list of names and city of residence in a array and need to sort this array by comparing the city of residence. List has to be sorted in alphabetical order. Comparator has been set up and works I'm just kinda lost with the insertion sorter programming as this is the first time we are doing that method of sorting.
Here's what I've tried so far:
public void InsertionSort()
{
for (int i = 0; i < Count; i++)
{
Student cur = Attendees[i];
for (int j = 0; j < Count; j++)
{
Student Sel = Attendees[j];
if (cur.CompareTo(Sel) < 0)
{
Student temp = Attendees[j];
Attendees[j] = Attendees[i];
for (int k = i; k > j; k--)
Attendees[k] = Attendees[k - 1];
Attendees[k + 1] = temp;
}
}
}
}
Try like this...
public void InsertionSort()
{
for (int i = 0; i < Count; i++)
{
int j = i;
While(j > 0)
{
Student cur = Attendees[j];
Student sel = Attendees[j-1];
if (cur.CompareTo(Sel) < 0)
{
Student temp = cur;
cur = sel;
sel = temp;
j--
}
else
break;
}
}
}
public void InsertionSort()
{
for (int i = 1; i < Count; i++) // Iterate beginning at 1, because we assume that 0 is already sorted
{
for (int j = i; j > 0; j--) // Iterate backwards, starting from 'i'
{
Student cur = Attendees[j - 1];
Student tbs = Attendees[j]; // 'tbs' == "to be sorted"
if (cur.CompareTo(tbs) < 0) // usually, classes that implement 'CompareTo()' also implement 'operator <()', 'operator >()' and 'operator ==()', so you could have just written 'cur < tbs'
{
Student temp = Attendees[j];
Attendees[j] = Attendees[j - 1];
Attendees[j - 1] = temp;
}
else
break; // since 'tbs' is no longer > 'cur', it is part of our sorted list. We don't need to sort that particular 'tbs' any further
}
}
}
Keep in mind, that this algorithm sorts your list in descending order.
int[] newarr = {2,1,5,3,7,6};
int a, b;
for (int i = 1; i < newarr.Length; i++)
{
a = newarr[i];
b = i - 1;
while(b>=0 && newarr[b]>a)
{
newarr[b+1] = newarr[b];
b=b-1;
}
newarr[b+1] = a;
}

Categories

Resources