Initialize an object after it is referenced by an other - c#

I've got a 2 Dimensional array, which stores fields of a chessboard..
private field[,] board = new field[boardsize,boardsize];
..now when I initialize them I want to reference to the neighbours of every field, which are partly not initilized yet.
At the moment a use a work-around like this:
for(int x = 0; x < boardsize ; x++)
{
for(int y = 0; y < boardsize ; y++)
{
board[x,y] = new field();
}
}
for(int x = 0; x < boardsize ; x++)
{
for(int y = 0; y < boardsize ; y++)
{
board[x,y].setNeighbours(x, y, board);
}
}
This works fine but I'm interested if its possible to set the neighbours before or at time of the initialisation.
setNeighbour - Method:
setNeighbour(int x, int y, field[,])
{
if(field[x-1,y] != null)
this.neighbour[0] = field[x-1,y];
if(field[x-1,y+1] != null)
this.neighbour[0] = field[x-1,y+1];
if(field[x,y+1] != null)
this.neighbour[0] = field[x,y+1];
if(field[x+1,y+1] != null)
this.neighbour[0] = field[x+1,y+1];
if(field[x+1,y] != null)
this.neighbour[0] = field[x+1,y];
if(field[x+1,y-1] != null)
this.neighbour[0] = field[x+1,y-1];
if(field[x,y-1] != null)
this.neighbour[0] = field[x,y-1];
if(field[x-1,y-1] != null)
this.neighbour[0] = field[x-1,y-1];
}

You could do this:
private field[,] board = new field[boardsize,boardsize];
for(int x = 0; x < boardsize ; x++)
{
for(int y = 0; y < boardsize ; y++)
{
if(board[x,y] == null)
board[x,y] = new field();
board[x,y].setNeighbours(x, y, board);
}
}
and check initialization of the neighbour in the setNeighbours() method the same way:
private void setNeighbours(int x, int y, field[,] board)
{
//Initialize neighbour if not already initialized
if(board[x+1,y] == null)
board[x+1,y] = new field();
//DO SOMETHING...
}

I don't Believe it's possible to reference the neighbours since they aren't created yet. You could however add the board as a parameter to the constructor of field and use a property to look up the neighbours when needed later.

This is a classical problem... Sadly C# doesn't have continuations... They can be simulated (very slowly) through the use of Threads... Yes, it is overkill, and it is only an exercise in programming:
public sealed class WaitForReady<T> : IDisposable
{
public readonly ManualResetEvent mre = new ManualResetEvent(false);
public T Value
{
get
{
mre.WaitOne();
return this.value;
}
set
{
this.value = value;
mre.Set();
}
}
private T value;
#region IDisposable Members
public void Dispose()
{
mre.Dispose();
}
#endregion
}
public class Field
{
public Field[] Neighbours;
public Field(WaitForReady<Field> me, WaitForReady<Field>[] neighbours)
{
me.Value = this;
Neighbours = new Field[neighbours.Length];
for (int i = 0; i < neighbours.Length; i++)
{
Neighbours[i] = neighbours[i] != null ? neighbours[i].Value : null;
}
}
}
public static void Main(string[] args)
{
int boardsize = 8;
Field[,] board = new Field[boardsize, boardsize];
WaitForReady<Field>[,] boardTemp = null;
try
{
boardTemp = new WaitForReady<Field>[boardsize, boardsize];
var threads = new Thread[boardsize * boardsize];
for (int i = 0; i < boardsize; i++)
{
for (int j = 0; j < boardsize; j++)
{
boardTemp[i, j] = new WaitForReady<Field>();
}
}
int k = 0;
for (int i = 0; i < boardsize; i++)
{
for (int j = 0; j < boardsize; j++)
{
var neighbours = new WaitForReady<Field>[8];
neighbours[0] = i > 0 && j > 0 ? boardTemp[i - 1, j - 1] : null;
neighbours[1] = i > 0 ? boardTemp[i - 1, j] : null;
neighbours[2] = i > 0 && j + 1 < boardsize ? boardTemp[i - 1, j + 1] : null;
neighbours[3] = j > 0 ? boardTemp[i, j - 1] : null;
neighbours[4] = j + 1 < boardsize ? boardTemp[i, j + 1] : null;
neighbours[5] = i + 1 < boardsize && j > 0 ? boardTemp[i + 1, j - 1] : null;
neighbours[6] = i + 1 < boardsize ? boardTemp[i + 1, j] : null;
neighbours[7] = i + 1 < boardsize && j + 1 < boardsize ? boardTemp[i + 1, j + 1] : null;
int i1 = i, j1 = j;
threads[k] = new Thread(() => board[i1, j1] = new Field(boardTemp[i1, j1], neighbours));
threads[k].Start();
k++;
}
}
// Wait for all the threads
for (int i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
}
finally
{
// Dispose the WaitForReady
if (boardTemp != null)
{
for (int i = 0; i < boardsize; i++)
{
for (int j = 0; j < boardsize; j++)
{
if (boardTemp[i, j] != null)
{
boardTemp[i, j].Dispose();
}
}
}
}
}
}
The "trick" here is to create the Fields in 64 separate threads. When initialized first a Field "announce" itself to everyone (by setting its corresponding WaitForReady<> object), then it asks its neighbours for their this reference. It does this through the WaitForReady<> objects it receives as a parameters. The WaitForReady<> is a "special" container that can contain a single value (Value). If Value isn't set, then asking for it will put the thread in wait, until someone sets the value through the set.
For small sizes it is possible to build everything using recursion to simulate continuations. For a board size of 64 it is normally possible. This is faster.
public class Field
{
public Field[] Neighbours;
public Field(int i, int j, int boardsize, Func<Field>[,] getters)
{
Console.WriteLine("Building [{0},{1}]", i, j);
getters[i, j] = () => this;
Neighbours = new Field[8];
Neighbours[0] = i > 0 && j > 0 ? getters[i - 1, j - 1]() : null;
Neighbours[1] = i > 0 ? getters[i - 1, j]() : null;
Neighbours[2] = i > 0 && j + 1 < boardsize ? getters[i - 1, j + 1]() : null;
Neighbours[3] = j > 0 ? getters[i, j - 1]() : null;
Neighbours[4] = j + 1 < boardsize ? getters[i, j + 1]() : null;
Neighbours[5] = i + 1 < boardsize && j > 0 ? getters[i + 1, j - 1]() : null;
Neighbours[6] = i + 1 < boardsize ? getters[i + 1, j]() : null;
Neighbours[7] = i + 1 < boardsize && j + 1 < boardsize ? getters[i + 1, j + 1]() : null;
Console.WriteLine("Builded [{0},{1}]", i, j);
}
}
public static void Main(string[] args)
{
int boardsize = 8;
Field[,] board = new Field[boardsize, boardsize];
Func<Field>[,] getters = new Func<Field>[boardsize, boardsize];
for (int i = 0; i < boardsize; i++)
{
for (int j = 0; j < boardsize; j++)
{
int i1 = i, j1 = j;
getters[i, j] = () => board[i1, j1] = new Field(i1, j1, boardsize, getters);
}
}
for (int i = 0; i < boardsize; i++)
{
for (int j = 0; j < boardsize; j++)
{
getters[i, j]();
}
}
}

Another way is to let the Fields handle creation of the other fields.
It's gonna be a lot more work to write all the code, but it should be more processor efficient.
Turns out you can't do it in the constructor because you'll get into an infinite loop of fields trying to create each other (because they can't find each other yet).
I like doing things like aggressive inlining even though it only makes a tiny difference in Release mode and actually slows the code down in Debug mode. On my machine it was about .1 sec for 10k executions. Would be interested to know if that's any faster than #xanatos's answer. It's certainly a lot more code :P
using System.Runtime.CompilerServices;
namespace Algorithms
{
public class Board
{
public Field[,] fields = new Field[8, 8];
}
public class Field
{
// Neighbor positions
// 701 +1-1 +10 +1+1
// 6 2 0-1 00 0+1
// 543 -1-1 -10, -1+1
private Field[] neighbors = new Field[8];
public void FindNeighbors(Board board, int rank, int file)
{
if (rank > 0)
{
// Not on bottom
createNeighbor(board, rank - 1, file, 4);
if (file > 0)
{
// Not in bottom-left corner, so adding it
//createNeighbor(board, rank - 1, file, 4);
createNeighbor(board, rank - 1, file - 1, 5);
createNeighbor(board, rank, file - 1, 6);
if (rank < 7)
{
// Not on top corner, so adding above and left-above
createNeighbor(board, rank + 1, file - 1, 7);
createNeighbor(board, rank + 1, file, 0);
if (file < 7)
{
// Not in any corder, adding remainder
createNeighbor(board, rank, file + 1, 2);
createNeighbor(board, rank - 1, file + 1, 3);
createNeighbor(board, rank + 1, file + 1, 1);
}
else
{
// On the right, the only fields that haven't been added yet are on the right
}
}
else
{
// on top
if (file < 7)
{
// Not on the left, so add those fields.
createNeighbor(board, rank, file + 1, 2);
createNeighbor(board, rank - 1, file + 1, 3);
}
else
{
// On the top-left, so nothing else to add.
}
}
}
else
{
createNeighbor(board, rank, file + 1, 2);
createNeighbor(board, rank - 1, file + 1, 3);
if (rank < 7)
{
createNeighbor(board, rank + 1, file, 0);
createNeighbor(board, rank + 1, file + 1, 1);
}
else
{
// Top-left corner, nothing to add
}
}
}
else
{
// Bottom
createNeighbor(board, rank + 1, file, 0);
if (file > 0)
{
// Not on left
createNeighbor(board, rank, file - 1, 6);
createNeighbor(board, rank + 1, file - 1, 7);
if (file < 7)
{
// Not on the right
createNeighbor(board, rank + 1, file + 1, 1);
createNeighbor(board, rank, file + 1, 2);
}
}
else
{
// Bottom-left corner
createNeighbor(board, rank + 1, file + 1, 1);
createNeighbor(board, rank, file + 1, 2);
}
}
}
// Neighbor positions
// 701 +1-1 +10 +1+1
// 6 2 0-1 00 0+1
// 543 -1-1 -10, -1+1
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void createNeighbor(Board board, int rank, int file, int neighbor)
{
var field = board.fields[rank, file];
if (field == null)
{
field = new Field();
board.fields[rank, file] = field;
// Start looking for neighbors after their object is initialized.
field.FindNeighbors(board, rank, file);
}
// Always copy a link to the field, even if it already existed
neighbors[neighbor] = field;
}
}
}

Related

Counting Sort Implementation in C#

I am implementing counting sort But some thing is wrong with my code
I am new in Programming Please help me to find an error.
I am implenting it step by step .
namespace ConsoleApplication1
{
class Program
{
public static int[] a = { 0,0,0,5,4,8,9,9,7,3, 3, 2, 1 };
public static void Sorting()
{
int j = 0, i = 0, smallestvalue = 0, largestvalue = 0, n = a.Length, lengthof_B = 0, temp = 0, anothersmallestvalue;
smallestvalue = largestvalue = a[0];
for (i = 0; i < n; i++)
{
if (smallestvalue > a[i])
{
smallestvalue = a[i];
}
else if (largestvalue < a[i])
{
largestvalue = a[i];
}
}
int x = anothersmallestvalue = smallestvalue;
lengthof_B = largestvalue - smallestvalue + 1;
int[] b = new int[lengthof_B];
for (i = 0; i < lengthof_B && smallestvalue <= largestvalue; i++)
{
for (j = 0; j < n; j++)
{
if (smallestvalue == a[j])
{
b[i] = b[i] + 1;
}
}
b[i] = temp + b[i];
temp = b[i];
smallestvalue++;
}
int[] c = new int[a.Length];
// I think error here
for (i = n - 1; i >= 0; i--)
{
anothersmallestvalue = x;
for (j = 0; j <= lengthof_B ; j++)
{
if (a[i] == anothersmallestvalue)
{
temp = b[j];
c[temp - 1] = anothersmallestvalue;
b[j] = b[j];
}
anothersmallestvalue++;
}
}
for (i = 0; i < c.Length; i++)
{
Console.WriteLine("c[i] : " + c[i]);
}
}
}
class Demo
{
static void Main(string[] args)
{
Program.Sorting();
Console.ReadLine();
}
}
}
Desired Output is
000123457899
But output of my program is
000120457809
This Is Your Code Here I found a mistake.
And your Code is too complex Please Go through your code Once more.
for (i = n - 1; i >= 0; i--)
{
anothersmallestvalue = x;
for (j = 0; j <= lengthof_B ; j++)
{
if (a[i] == anothersmallestvalue)
{
temp = b[j];
c[temp - 1] = anothersmallestvalue;
b[j] = b[j] -1 ;// Possible Mistake I think here
}
anothersmallestvalue++;
}
}
the very simple and stylish way is described and shown here.
en.wikipedia.org/wiki/Counting_sort#The_algorithm
Normal sorting your two loops should look like this
for (i = 0; i < lengthof_B - 1; i++)
{
for (j = i + 1; j < lengthof_B; j++)
{
}
}​

How to find possible set of k Elements from array?

I have an array {1,2,3,4,5,6,7,8,9,10} and I have to find all combinations of k elements from array and k will be dynamic. So for 4 elements below code is sufficient but i have to make this dynamic means,it is not fixed that how many for loops will be used, so please suggest some solution for this.
for (i = 0; i < len - 3; i++)
{
for (j = i + 1; j < len - 2; j++)
{
for (y = j + 1; y < len - 1; y++)
{
for (k = y + 1; k < len; k++)
Console.WriteLine("{0},{1},{2},{3}", s[i], s[j],s[y], s[k]);
}
}
}
All you need is to replace i, j, y, ... with array and manually unroll the for loops like this
static void PrintCombinations(int[] input, int k)
{
var indices = new int[k];
for (int pos = 0, index = 0; ; index++)
{
if (index <= input.Length - k + pos)
{
indices[pos++] = index;
if (pos < k) continue;
// Consume the combination
for (int i = 0; i < k; i++)
{
if (i > 0) Console.Write(",");
Console.Write(input[indices[i]]);
}
Console.WriteLine();
pos--;
}
else
{
if (pos == 0) break;
index = indices[--pos];
}
}
}
You can use this methods for generating combinations of size l
public static List<List<T>> GenerateCombinations<T>(List<T> items, int l)
{
if (l == 0)
return new List<List<T>> { new List<T>() };
var allCombs = new List<List<T>>();
for (int i = 0; i < items.Count(); i++)
{
var listWithRemovedElement = new List<T>(items);
listWithRemovedElement.RemoveRange(0, i + 1);
foreach (var combination in GenerateCombinations(listWithRemovedElement, l - 1))
{
var comb = new List<T>(listWithRemovedElement.Count + 1);
comb.Add(items[i]);
comb.AddRange(combination);
allCombs.Add(comb);
}
}
return allCombs;
}
You can use this methods for generating permutations of size l
public static List<List<T>> GeneratePermutations<T>(List<T> items, int l)
{
if (l == 0)
return new List<List<T>> { new List<T>() };
var allCombs = new List<List<T>>();
for (int i = 0; i < items.Count(); i++)
{
var listWithRemovedElement = new List<T>(items);
listWithRemovedElement.RemoveAt(i);
foreach (var combination in GeneratePermutations(listWithRemovedElement, l - 1))
{
var comb = new List<T>(listWithRemovedElement.Count + 1);
comb.Add(items[i]);
comb.AddRange(combination);
allCombs.Add(comb);
}
}
return allCombs;
}
Permutationsof { 1, 2, 3 } with size of 2
var result = GeneratePermutations(new List<int>() { 1, 2, 3 }, 2);
foreach (var perm in result)
Console.WriteLine(string.Join(",", perm));
1,2
1,3
2,1
2,3
3,1
3,2
Combinations of { 1, 2, 3 } with size of 2
var result = GenerateCombinations(new List<int>() { 1, 2, 3 }, 2);
foreach (var comb in result)
Console.WriteLine(string.Join(",", comb));
1,2
1,3
2,3
This isn't how I'd do it in "real life", but since this seems to be a simple homework-style problem aimed at getting you to use recursion and with the aim of simply writing out the combinations, this is a reasonably simple solution:
class Program
{
public static void Main()
{
int[] test = { 1, 2, 3, 4, 5 };
int k = 4;
WriteCombinations(test, k);
Console.ReadLine();
}
static void WriteCombinations(int[] array, int k, int startPos = 0, string prefix = "")
{
for (int i = startPos; i < array.Length - k + 1; i++)
{
if (k == 1)
{
Console.WriteLine("{0}, {1}", prefix, array[i]);
}
else
{
string newPrefix = array[i].ToString();
if (prefix != "")
{
newPrefix = string.Format("{0}, {1}", prefix, newPrefix);
}
WriteCombinations(array, k - 1, i + 1, newPrefix);
}
}
}
}
If having optional parameters is not "basic" enough, then you can either take away the default values and pass in 0 and "" on the first call, or you can create another "wrapper" method that takes fewer parameters and then calls the first method with the defaults.

C#, one-dimension wrapping array

I have a one-dimensional array, and I need to run operations on it based on the adjacents cells of every cell.
For instance:
To run the operations on the first cell, I'll need to access the last cell and the second.
The second cell, I'll need to access the first cell and the third cell.
The last cell, I'll need to access the first cell and the one before the last cell.
My code so far is:
public static int[] firstRule(int[] numberArray)
{
for (int i = 0; i < numberArray.Length; i++)
{
if (numberArray[numberArray.Length - 1 - i] == numberArray[i] + 1
&& numberArray[i + 1] == numberArray[i] + 1)
{
numberArray[i] = numberArray[i] - 1;
}
}
return numberArray;
}
But the problem with my approach is that it would only work for the first cell, as it would take the last cell and the second cell correctly, but after that, everything would fall apart. I don't like posting without a lot of code but I have no clue how to follow this up.
I am trying to achieve the following:
Those values are numbers ranging from 0 to 3. If both the cell before and the cell after is the same number, I want to change it to x + 1
For instance: suppose I have 1 0 1 2 2. I would want to change 0 to 1. As the neighbor cells are both 0.
Just keep it simple and use variables to calculate the left and right cell indices. Inside your for loop you can do this...
var leftCell = i - 1;
if (leftCell < 0)
{
leftCell = numberArray.Length - 1; // Wrap around to the end...
}
var rightCell = i + 1;
if (rightCell > numberArray.Length - 1)
{
rightCell = 0; // Wrap back around to the beginning...
}
// Now you can update your original code to use these computed indices...
if (numberArray[leftCell] == numberArray[i] + 1
&& numberArray[rightCell] == numberArray[i] + 1)
{
numberArray[i] = numberArray[i] - 1;
}
Try this out:
var len = numberArray.Length;
for (int i = 0; i < len; i++)
{
var leftIndex = (i - 1 + len) % len;
var rightIndex = (i + 1) % len;
// do your stuff with numberArray[leftIndex] and numberArray[rightIndex]
}
% is mod operator. % len allows you to stay in range 0..len-1, so you can walk through array as if it has become 'cyclic'
From your comments.
Those values are numbers ranging from 0 to 3. If both the cell before and the cell after is the same number, I want to change it to x + 1
For instance: suppose I have 1 0 1 2 2. I would want to change 0 to 1. As the neighbor cells are both 0.
I would create a new array, populate it with the values of the existing array and then change the values of the new array according to the results of the value in the existing array.
Edit as Op is getting wrong values
I suspect you may not be copying the array correctly instead:
Existing Array array // The array you are passing in as parameter.
Declare a new empty array:
int[] newArray;
int size = array.length;
for(int i =1; i<size-1;i++){
if(array[i-1]==array[i+1])){
newArray[i]=array[i]+1;
}
else{
newArray[i]=array[i];
}
}
if(array[size-1]==array[0]){
newArray[size]= array[size]+1;
}
else{
newArray[i]=array[i];
}
if(array [size]==array[1]){
newArray[0]= array[0]+1;
}
else{
newArray[i]=array[i];
}
if there is a limit to the number and it reverts to zero after 2, then just do a simple if test for that.
int[] arr = new int[] { 1, 2, 3, 4, 5 };
var triples = arr.Select((n, i) =>
{
if (i == 0)
return Tuple.Create(arr[arr.Length - 1], arr[0], arr[1]);
else if (i == arr.Length - 1)
return Tuple.Create(arr[i - 1], arr[i], arr[0]);
else
return Tuple.Create(arr[i - 1], arr[i], arr[i + 1]);
});
foreach (var triple in triples)
{
Console.WriteLine(triple.Item1 + " " + triple.Item2 + " " + triple.Item3);
}
public static void firstRule(int[] numberArray)
{
for (int i = 0; i < numberArray.Length; i++)
{
int? prevElement = i == 0
? numberArray[numberArray.Length-1]
: numberArray[i - 1];
int? nextElement = i == numberArray.Length -1
? numberArray[0]
: numberArray[i + 1];
Console.WriteLine(
String.Format("Prev: {0}; Current: {1}; Next: {2}",
prevElement,
numberArray[i],
nextElement)
);
}
}
And then calling firstRule(new int[]{ 1, 2, 3 }); prints:
Prev: 3; Current: 1; Next: 2
Prev: 1; Current: 2; Next: 3
Prev: 2; Current: 3; Next: 1
OPTION 1
assign regardless
public static int[] firstRule(int[] numberArray)
{
int left,right;
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
left = (i == 0) ? max : i - 1;
right = (i == max) ? 0 : i + 1;
numberArray[i] = (numberArray[left] == numberArray[right]) ? numberArray[i] + 1 : numberArray[i]; //always peforms an assignment;
}
return numberArray;
}
OPTION 2
conditionally assign
public static int[] secondRule(int[] numberArray)
{
int left,right;
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
left = (i == 0) ? max : i - 1;
right = (i == max) ? 0 : i + 1;
if (numberArray[left] == numberArray[right])
{
numberArray[i]++;
}
}
return numberArray;
}
OPTION 3
left and right are only used 1 time in each iteration.. so why bother assigning them to a variable???...
public static int[] thirdRule(int[] numberArray)
{
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
if (numberArray[(i == 0) ? max : i - 1] == numberArray[(i == max) ? 0 : i + 1])
{
numberArray[i]++; // what happens if numberArray[i] is 3, should it become 4 or 0?
}
}
return numberArray;
}
OPTION 4 (UNSAFE)
unsafe - fixed - pointers
public static int[] fourthRule(int[] numberArray)
{
unsafe {
int* pointer, right, left;
for (int i = 0, max = numberArray.Length - 1; i <= max; i++)
{
fixed (int* p1 = &numberArray[0], p2 = &numberArray[i], p3 = &numberArray[max])
{
pointer = p2;
if (i == 0)
{
left = p3;
right = pointer;
right++;
}
else if (i == max)
{
left = pointer;
left--;
right = p1;
}
else
{
left = pointer;
left--;
right = pointer;
right++;
}
if (*right == *left) {
*pointer = *pointer + 1;
}
}
}
}
return numberArray;
}
Recently came up against this myself and found this to be a solid method.
`
int length = numberArray.Length;
for (int i = 0; i < length; ++i)
{
int iMinus = (((i - 1) % length) + length) % length;
int iPlus = (((i + 1) % length) + length) % length;
}`
Something like this should work. It determines the appropriate cells for the operation in each loop and executes the operation. You didn't state what that operation was so you need to fill in the DoYourOperation method.
public static int[] processArray(int[] numberArray)
{
for (int i= 0; i < numberArray.Length; i++)
{
int firstCell;
int secondCell;
//Check if first cell
if(i == 0)
{
firstCell = numberArray[numberArray.length-1]; //Last cell
secondCell = numberArray[i++]; //Next cell
}
//Check if last cell
else if(i == numberArray.Length - 1)
{
firstCell = numberArray[i--]; //Cell before last one
secondCell = numberArray[0]; //First cell
}
else
{
firstCell = numberArray[i--];
secondCell = numberArray[i++];
}
DoYourOperation(firstCell, secondCell);
}
}

MergeSort Implementation in C#

Currently studying algorithm analysis, and instead of blindly running off of pseudo-code from my textbook, I'm implementing each algorithm in C#. This is the psuedo-code:
MERGE-SORT(A,p,r)
1 if p < r
2 q = (p+r)/2
3 MERGE-SORT(A,p,q)
4 MERGE-SORT(A,q+1,r)
5 MERGE(A,p,q,r)
MERGE(A,p,q,r)
1 n1 = q - p + 1
2 n2 = r - q
3 let L[1..n1+1] and R[1..n2+1] be new arrays
4 for i = 1 to n1
5 L[i] = A[p+i-1]
6 for j = 1 to n2
7 R[j] = A[q+j]
8 L[n1+1] = INF
9 R[n1+1] = INF
10 i = 1
11 j = 1
12 for k = p to r
13 if L[i] <= R[j]
14 A[k] = L[i]
15 i = i + 1
16 else
17 A[k] = R[j]
18 j = j + 1
This is my code:
static void Main(string[] args)
{
int[] unsortedArray = new int[] { 5, 2, 7, 4, 1, 6, 8, 3, 9, 10 };
MergeSort(ref unsortedArray, 1, unsortedArray.Length);
foreach (int element in unsortedArray)
{
Console.WriteLine(element);
}
Console.Read();
}
private static void MergeSort(ref int[] unsortedArray, int leftIndex, int rightIndex)
{
if (leftIndex < rightIndex)
{
int middleIndex = (leftIndex + rightIndex) / 2;
//Sort left (will call Merge to produce a fully sorted left array)
MergeSort(ref unsortedArray, leftIndex, middleIndex);
//Sort right (will call Merge to produce a fully sorted right array)
MergeSort(ref unsortedArray, middleIndex + 1, rightIndex);
//Merge the sorted left & right to finish off.
Merge(ref unsortedArray, leftIndex, middleIndex, rightIndex);
}
}
private static void Merge(ref int[] unsortedArray, int leftIndex, int middleIndex, int rightIndex)
{
int lengthLeft = middleIndex - leftIndex + 1;
int lengthRight = rightIndex - middleIndex;
int[] leftArray = new int[lengthLeft + 1];
int[] rightArray = new int[lengthRight + 1];
for (int i = 0; i < lengthLeft; i++)
{
leftArray[i] = unsortedArray[leftIndex + i - 1];
}
for (int j = 0; j < lengthRight; j++)
{
rightArray[j] = unsortedArray[middleIndex + j];
}
leftArray[lengthLeft] = Int32.MaxValue;
rightArray[lengthRight] = Int32.MaxValue;
int iIndex = 0;
int jIndex = 0;
for (int k = leftIndex; k < rightIndex; k++)
{
if (leftArray[iIndex] <= rightArray[jIndex])
{
unsortedArray[k] = leftArray[iIndex];
iIndex++;
}
else
{
unsortedArray[k] = rightArray[jIndex];
jIndex++;
}
}
}
I'm not sure where I'm messing things up -- I tried to follow the pseudo-code as well as I could, but my output is funky (i.e. repeated values and not properly sorted).
Debugging this didn't help me figure out the problem either (recursive solutions get too messy).
Where am I going wrong, and how do I fix it?
As correctly pointed out in the comments, C# array indexing is zero-based, while your pseudo code is one-based.
That being said, here's the errors:
1) Main method
MergeSort(ref unsortedArray, 1, unsortedArray.Length);
has to be changed to:
MergeSort(ref unsortedArray, 0, unsortedArray.Length - 1);
2) Merge method
leftArray[i] = unsortedArray[leftIndex + i - 1];
has to be change to:
leftArray[i] = unsortedArray[leftIndex + i];
3) Merge method
rightArray[j] = unsortedArray[middleIndex + j];
has to be change to:
rightArray[j] = unsortedArray[middleIndex + j + 1];
4) Merge method
for (int k = leftIndex; k < rightIndex; k++)
has to be change to:
for (int k = leftIndex; k <= rightIndex; k++)
BTW, the ref keyword in your code is not really necessay, since you're just modifying the values inside the array and not creating a new instance of it .
private static void Merge(int[]A, int[]aux, int lo, int mid, int hi)
{
for (int k = lo; k <= hi; k++)
aux[k] = A[k];
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid) A[k] = aux[j++];
else if (j > hi) A[k] = aux[i++];
else if (aux[j] < aux[i]) A[k] = aux[j++];
else A[k] = aux[i++];
}
}
private static void Sort(int[] A, int[] aux, int lo, int hi)
{
if (hi <= lo) return;
int mid = lo + (hi - lo) / 2;
Sort(A, aux, lo, mid);
Sort(A, aux, mid + 1, hi);
if (A[mid + 1] > A[mid]) return;
Merge(A, aux, lo, mid, hi);
}
public static void Sort(int[] A)
{
int[] aux = new int[A.Length];
Sort(A, aux, 0, A.Length - 1);
}
A Simple Merge Sort Implementation.
https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/MergeSort.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace AlgorithmsMadeEasy
{
class MergeSort
{
public void MergeSortMethod()
{
var input = System.Console.ReadLine();
string[] sInput = input.Split(' ');
int[] numbers = Array.ConvertAll(sInput, int.Parse);
int len = numbers.Length;
MergeSort_Recursive(numbers, 0, len - 1);
for (int i = 0; i < len; i++)
{
Console.Write(numbers[i] + " ");
}
Console.ReadLine();
}
static public void MergeSort_Recursive(int[] numbers, int left, int right)
{
int mid;
if (right > left)
{
mid = (right + left) / 2;
MergeSort_Recursive(numbers, left, mid);
MergeSort_Recursive(numbers, (mid + 1), right);
DoMerge(numbers, left, (mid + 1), right);
}
}
static public void DoMerge(int[] numbers, int left, int mid, int right)
{
int[] temp = new int[numbers.Length];
int i, left_end, num_elements, tmp_pos;
left_end = (mid - 1);
tmp_pos = left;
num_elements = (right - left + 1);
while ((left <= left_end) && (mid <= right))
{
if (numbers[left] <= numbers[mid])
temp[tmp_pos++] = numbers[left++];
else
temp[tmp_pos++] = numbers[mid++];
}
while (left <= left_end)
temp[tmp_pos++] = numbers[left++];
while (mid <= right)
temp[tmp_pos++] = numbers[mid++];
for (i = 0; i < num_elements; i++)
{
numbers[right] = temp[right];
right--;
}
}
}
}
/*
Sample Input:
6 5 3 2 8
Calling Code:
MergeSort ms = new MergeSort();
ms.MergeSortMethod();
*/

Out of memory and overflow exceptions creating small array

I am new to C# and XNA. Have just managed to write a class that generates a triangular grid.
But there is one problem. I can get maximum 27 nodes length triangle.
At 28 it throws Out of memory exception and at 31 -overFlow exception.
I don't understand how it overflows or out of memory... Tried to
calculate all those memory values but they look very tiny.
It is only array of nodes affected by variable. Node class is not very big:
float x; 4 B
float y; 4 B
float z; 4 B
int[] con; int[6] 4*6=24 B
byte pass; 1 B
Color col; 32 b= 4 B
Total: 41B
sequence sum of nodes needed to create triangle is n(n+1)/2
out of memory at 28
28*29/2=406 nodes
total memory:
41*406 = 16646 B = 16.26 kB
Overflows at 31: 496 nodes is 19.9 kB
I did read articles about "out of memory exceptions", that structures size is bigger than it seems and that out of memory happens at sizes of 500MB... there is no way my small triangle would reach such huge size.
This is my whole class:
class TriMatrix
{
int len;
int Lenght;
Node[] node;
VertexPositionColor[] vertex;
public class Node
{
public float x;
public float y;
public float z;
public int[] con;
public byte pass;
public Color col;
public Node(byte passable)
{
pass = passable;
if (pass > 0)
{ col = Color.Green; }
else
{ col = Color.DarkRed; }
x = 0;
z = 0;
con = new int[6];
}
}
public TriMatrix(int lenght)
{
len = lenght;
Lenght = 0;
byte pass;
Random rnd = new Random();
for (int i = 0; i <= len; i++)
{
Lenght += Lenght + 1;
}
node = new Node[Lenght];
int num = 0;
for (int i = 0; i < len; i++)
{
for (int j = 0; j <= i; j++)
{
if (rnd.Next(0, 5) > 0) { pass = 1; } else { pass = 0; }
node[num] = new Node(pass);
node[num].x = (float)i - (float)j / 2.0f;
node[num].y = 0;
node[num].z = (float)j * 0.6f;
if (i < len - 1) { node[num].con[0] = num + i; } else { node[num].con[0] = -1; node[num].col = Color.Violet; }
if (i < len - 1) { node[num].con[1] = num + i + 1; } else { node[num].con[1] = -1; }
if (j < i) { node[num].con[2] = num + 1; } else { node[num].con[2] = -1; node[num].col = Color.Violet; }
if (j < i) { node[num].con[3] = num - i; } else { node[num].con[3] = -1; }
if (i > 0) { node[num].con[4] = num - i - 1; } else { node[num].con[4] = -1; }
if (i > 0) { node[num].con[5] = num - 1; } else { node[num].con[5] = -1; }
if (j == 0) { node[num].col = Color.Violet; }
num++;
}
}
}
public void Draw(Effect effect, GraphicsDevice graphics)
{
VertexPositionColor[] verts = new VertexPositionColor[3];
int num = 0;
for (int i = 0; i < len-1; i++)
{
for (int j = 0; j <= i; j++)
{
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
verts[1] = new VertexPositionColor(new Vector3(node[num + i + 1].x, node[num + i + 1].y, node[num + i + 1].z), node[num + i + 1].col);
verts[2] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);
if ( j < i)
{
verts[0] = new VertexPositionColor(new Vector3(node[num].x, node[num].y, node[num].z), node[num].col);
verts[1] = new VertexPositionColor(new Vector3(node[num + i + 2].x, node[num + i + 2].y, node[num + i + 2].z), node[num + i + 2].col);
verts[2] = new VertexPositionColor(new Vector3(node[num + 1].x, node[num + 1].y, node[num + 1].z), node[num + 1].col);
graphics.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, verts, 0, 1);
}
}
num++;
}
}
}
}// endclass
I assume that your bug lies in this loop (taking the liberty to correct your spelling):
for (int i = 0; i <= len; i++)
{
Length += Length + 1;
}
Within the loop, you are incrementing the value of Length by itself plus one. This effectively means that you are doubling the value of Length for each iteration, resulting in exponential growth.
During the first few iterations, the values of Length will be: 1, 3, 7, 15, 31, 63, …. We can generalize this sequence such that, at iteration i, the value of Length will be 2i+1−1. At iteration 28, this would be 536,870,911. At iteration 31, this would be 4,294,967,295.
Edit: As you mentioned in the comment below, the correct fix for computing the number of elements in a triangular grid of length len would be:
for (int i = 1; i <= len; i++)
{
Length += i;
}
This is equivalent to the summation 1 + 2 + 3 + … + len, which computes what is known as the triangular number. It may be succinctly computed using the formula:
Length = len * (len + 1) / 2;
The reason that this number grows so large is that it is a square relation; for a side of length n, you need an area of approximately half of n².

Categories