fill a 2D array as a diamond shape - c#

I want to fill my array with struct in a way that it will look like this
I have this code so far :
`for (int i = 1; i <= n; i++)
{
for (int j = 0; j <=(n - i); j++)
//i should fill m[,] here
for (int j = 1; j <= i; j++)
//i should fill m[,] here
for (int k = 1; k < i; k++)
//i should fill m[,] here
}
for (int i = n - 1; i >= 1; i--)
{
for (int j = 0; j < (n - i); j++)
//i should fill m[,] here
for (int j = 1; j <= i; j++)
//i should fill m[,] here
for (int k = 1; k < i; k++)
//i should fill m[,] here
}`
but I 'm a little bit confused with the index .
how can I adopt this code?

As it's unclear wether the array always has the size 5 I'll assume it has the size n with n being odd and n > 0 (The size is the x and the y size, as I assume that your matrix is quadratic). Then there are several ways to reach the goal your trying to reach, I'll try to present you one I thought of.
First of all we have to think about the array - as it's the easiest way, I'll assume it consists of boolean values (even though you said "I want to fill my array with struct", but as I'm not quite sure what you wanted to say with that and wether you really meant a struct, I'll let this up to you, as this shouldn't be the most difficult part):
var matrix = new bool[n,n];
Then we have to evalueate which fields have to be filled. Therefore we must realize a few things:
The filled fields are always central in their line
The first and last line always have one filled item
The following line always has two more/less filled items, so that the offset is one more than in the previous line
The center line has most items and is the turning point in the amount of filled items
As a first step in developing the algorithm, I'd write a function to fill lines of the array with specific amounts of fields:
private static void FillLine(int line, int count, bool[,] matrix)
{
//Firstly we have to evaluate the offset:
var offset = (matrix.GetLength(0) - count) / 2;
//Then we have to fill the line
for (var x = offset; x < offset + count; x++)
matrix[x, line] = true;
}
Now we simply have to fill the lines for the whole array:
public static void FillDiamond(bool[,] matrix)
{
var count = 1;
for (var line = 0; line < matrix.GetLength(1) / 2; line++)
{
FillLine(line, count, matrix);
count += 2;
}
FillLine(matrix.GetLength(1) / 2, count, matrix);
count = 1;
for (var line = matrix.GetLength(1) - 1; line > matrix.GetLength(1) / 2; line--)
{
FillLine(line, count, matrix);
count += 2;
}
}
Now in a console application you could use this like that:
using System;
namespace SO_c
{
internal static class Program
{
private static void Main()
{
while (true)
{
var n = int.Parse(Console.ReadLine());
if (n < 1 || n % 2 == 0)
continue;
var matrix = new bool[n, n];
FillDiamond(matrix);
for (var y = 0; y < matrix.GetLength(1); y++)
{
for (var x = 0; x < matrix.GetLength(0); x++)
Console.Write(matrix[x, y] ? "█" : " ");
Console.WriteLine();
}
}
}
private static void FillLine(int line, int count, bool[,] matrix)
{
//Firstly we have to evaluate the offset:
var offset = (matrix.GetLength(0) - count) / 2;
//Then we have to fill the line
for (var x = offset; x < offset + count; x++)
matrix[x, line] = true;
}
public static void FillDiamond(bool[,] matrix)
{
var count = 1;
for (var line = 0; line < matrix.GetLength(1) / 2; line++)
{
FillLine(line, count, matrix);
count += 2;
}
FillLine(matrix.GetLength(1) / 2, count, matrix);
count = 1;
for (var line = matrix.GetLength(1) - 1; line > matrix.GetLength(1) / 2; line--)
{
FillLine(line, count, matrix);
count += 2;
}
}
}
}
This can result in output like that:
That's it! Now you should get your diamond for every matrix that fits the rules :)

One way to do it is to calculate the center of the grid and fill in each row, from the center column. In each successive row, we increment the number of blocks we fill in on each side of the center column until we get to the center row, and then we decrement the number of blocks we fill in until we get to the end.
To determine how many blocks to put on each side of the center column for any given row, we can use the row index for the calculation.
Working our way from the top down to the center, the row index represents the number of blocks to add. So, for row index 0, we add 0 blocks on either side of the center column, row index 1 we add 1 block on each side, until we get to the center.
After we get to the center, we want to decrement the number of blocks each time, which can be done by subtracting the row index from the total number of rows.
The code says it better, I think:
private static void Main()
{
while (true)
{
// Get grid size from user and keep it between 1 and the window width
var gridSize = GetIntFromUser("Enter the size of the grid: ");
gridSize = Math.Min(Console.WindowWidth - 1, Math.Max(1, gridSize));
var grid = new bool[gridSize, gridSize];
var center = (gridSize - 1) / 2;
// Populate our grid with a diamond pattern
for (int rowIndex = 0; rowIndex < grid.GetLength(0); rowIndex++)
{
// Determine number of blocks to fill based on current row
var fillAmount = (rowIndex <= center)
? rowIndex : grid.GetUpperBound(0) - rowIndex;
for (int colIndex = 0; colIndex <= fillAmount; colIndex++)
{
grid[rowIndex, center - colIndex] = true;
grid[rowIndex, center + colIndex] = true;
}
}
// Display the final grid to the console
for (int row = 0; row < grid.GetLength(0); row++)
{
for (int col = 0; col < grid.GetLength(1); col++)
{
Console.Write(grid[row, col] ? "█" : " ");
}
Console.WriteLine();
}
}
}
Oh, and this is the helper function I used to get an integer from the user. It's pretty helpful to keep around because you don't have to do any validation in your main code:
private static int GetIntFromUser(string prompt)
{
int value;
// Write the prompt text and get input from user
Console.Write(prompt);
string input = Console.ReadLine();
// If input can't be converted to a double, keep trying
while (!int.TryParse(input, out value))
{
Console.Write($"'{input}' is not a valid number. Please try again: ");
input = Console.ReadLine();
}
// Input was successfully converted!
return value;
}
OUTPUT

Related

No Output for MergeSort Algorithm c#

In my project I've implemented MergeSort, bubble sort, and sequential search algorithms, however the Merge sort is not giving any output to the console, while the others work. I've tried debugging with no real luck.
public static void mergeSort(int[] a)
{
int inputLength = a.Length;
//sets the middle index to the total length divided by 2
int midIndex = a.Length / 2;
//sets the last index to the length minus one (minus one included so
an out of bounds exception is avoided
int endIndex = a.Length - 1;
//left side set to the middle index size
int[] leftArray = new int[midIndex];
//right side set to the total length minus the middle length
int[] rightArray = new int[inputLength - midIndex];
//looping from zero to middle of the array
for (int i = 0; i < midIndex; i++)
{
leftArray[i] = a[i];
}
//looping from the middle to the end of the array
for(int i = midIndex; i < inputLength; i++)
{
rightArray[i - midIndex] = a[i];
}
//recursively called the method to sort these two sides
mergeSort(leftArray);
mergeSort(rightArray);
//this calls the merge method to put the two halves together
merge(a, leftArray, rightArray);
}
private static void merge(int[] a, int[] leftHalf, int[] rightHalf)
{
int leftSize = leftHalf.Length;
int rightSize = rightHalf.Length;
int i = 0, j = 0, k = 0;
//loops until no more elements in left or right array
while(i < leftSize && j < rightSize)
{
if(leftHalf[i] <= rightHalf[j])
{
//sets the element at iteration k to the elements at i in the
left half if
//it is smaller than the right half
a[k] = leftHalf[i];
i++;
}
else
{
//if the right half is smaller, set element at iteration k
equal to the
//element at index j of the right half
a[k] = rightHalf[j];
j++;
}
k++;//iterate K
}
//these account for leftover elements after the above while loop.
while (i < leftSize)
{
a[k] = leftHalf[i];
i++;
k++;
}
while (j < rightSize)
{
a[k] = rightHalf[j];
j++;
k++;
}
}
My main method is here:
static void Main(string[] args)
{
try{
TextFileReader reader = new TextFileReader();
int[] numberArray = reader.ReadFile("numbers.txt");
//printArray(numberArray);
Sorts sorts = new Sorts();
//sorts.bubbleSort(numberArray);
//printArray(numberArray);
//sorts.selectionSort(numberArray);
Searches searches = new Searches();
//searches.SequentialSearch(numberArray, 897);
//searches.binarySearch(numberArray, 9992);
//Console.WriteLine("\n\nArray length: " + numberArray.Length);
mergeSort(numberArray);
printArray(numberArray);
}
catch(IOException ex)
{
Console.WriteLine("IO Exception Found.");
}
}
public static void printArray(int[] numberArray)
{
foreach(int i in numberArray)
{
Console.WriteLine(i);
}
}
}
}
This is driving me crazy because the other algorithms are working and outputting correctly, but when the MergeSort is ran it gives no exceptions or errors.

Building Conways game of life with C#

I am trying to calculate the Neighbour near my cells, but the code works for only the middle cells and not for the corner ones, for which I can use many if loops but I wanna know how it works with for and if loops.
I tried creating extra if loops or writing like if row ==0 etc. but everything seems to give me wrong answer. btw bool[,] grid has the values of false and true. and we need to calculate how many trues and false are their in give row/ col.
public static int CountNeighbours(bool[,] grid, int row, int col)
{
int total = 0;
for (int i = row - 1; i < row + 2; i++)
{
for (int j = col - 1; j < col + 2; j++)
{
if (grid[i, j] == grid[row, col])
{
total += 1;
}
}
}
Console.WriteLine("total neighbours for row {0} and column {1}: {2}",row,col,total-1);
return total-1;
}
The result should give perfect answer for corners and rows.
Your problem is that you count the cell itself as its own neighbour and that you don't check the boundaries of your grid.
Change your loop conditions like that:
for (int i = Math.Max(0, row - 1); i < row + 2 && i < grid.GetLength(0); i++)
{
for (int j = Math.Max(0, col - 1); j < col + 2 && j < grid.GetLength(1); j++)
{
if (i == row && j == col) continue; // skip current cell
So with Math.Max() you ensure that you don't use a negative i or j, because that would lead to an IndexOutOfRangeException.
With grid.GetLength() you get the array size in the respective dimension, because using a i or j greater or equal to that length would again raise an IndexOutOfRangeException.
And finally the last line checks that you don't count the cell in question itself.

Arrange elements in a matrix of any size

This is more of a discussion than a question per se since I could solve this with code but I think there should be better ways of doing this.
I need to distribute elements in a matrix so that each quadrant of the matrix (which dimensions aren't necessarily divisible by 4) contains an equal (or as close to equal as possible) number of said elements but is located randomly within that quadrant.
The rest of the matrix needs to contain random elements of a different type.
For instance, distributing 10 elements (A) in a 9x6 matrix could look like this:
Which reveals the problem of what to do with the middle lines when a dimension is odd. It could be included on one quadrant or the other randomly (the fact that there are no As in the 3 middle columns is just chance)
I first thought of dealing with this with a recursive function that divides into quadrants and randomly places each element.
I'm halfway through coding this in C#, the idea being something like this (it doesn't work as of yet and some things are inefficient to try to make the code more readable):
private void PopulateQuadrants(ref Test5Target[,] matrix,
int xBeginQuadrant, int xEndQuadrant, int yBeginQuadrant, int yEndQuadrant, int targets)
{
if (targets == 0)
{
return;
}
else if (targets == 1)
{
Random rand = new Random();
matrix[rand.Next(xBeginQuadrant, xEndQuadrant), rand.Next(yBeginQuadrant, yEndQuadrant)]
= new Test5Target(ChosenTarget, UseAdvancedTargets);
for (int x = xBeginQuadrant; x < xEndQuadrant; x++)
{
for (int y = xBeginQuadrant; y < xEndQuadrant; y++)
{
if (matrix[x, y] == null)
{
int type = rand.Next(TargetCount);
while(type == ChosenTarget){
type = rand.Next(TargetCount);
}
matrix[x, y] = new Test5Target(rand.Next(TargetCount), UseAdvancedTargets);
}
}
}
return;
}
else
{
int[] TargetsPerQuadrant = { targets / 4, targets / 4, targets / 4, targets / 4 };
int RemaindingTargets = targets % 4;
Random rand = new Random();
while (RemaindingTargets > 0)
{ // Randomly select quadrants to allocate the Remainding targets (one may end up with 3 extra as it is now)
TargetsPerQuadrant[rand.Next(4)]++;
RemaindingTargets--;
}
PopulateQuadrants(ref matrix, xBeginQuadrant, xEndQuadrant / 2, yBeginQuadrant, yEndQuadrant / 2, TargetsPerQuadrant[0]);
PopulateQuadrants(ref matrix, xEndQuadrant / 2, xEndQuadrant, yBeginQuadrant, yEndQuadrant / 2, TargetsPerQuadrant[1]);
PopulateQuadrants(ref matrix, xBeginQuadrant, xEndQuadrant / 2, yBeginQuadrant, yEndQuadrant / 2, TargetsPerQuadrant[2]);
PopulateQuadrants(ref matrix, xEndQuadrant / 2, xEndQuadrant, yBeginQuadrant / 2, yEndQuadrant, TargetsPerQuadrant[3]);
}
}
Is there any mathematically correct or simple or something way of achieving this or should I keep going in this way.
I finally decided to just place a minimum of a fourth of all elements in each corner randomly and the remainder also randomly ignoring odd lengths or just letting it skew toward one side or the other.
private Element[,] GetCancellationTestMatrix(int rows, int columns, int targets, int types)
{
// Supposing the different types of elements are just ints and we want a concrete type
// for our targets which is contained in the variable "TargetType"
Element[,] Matrix = new int[rows, columns];
Random rand = new Random();
int currQuadRowBegin = 0;
int currQuadRowEnd = rows / 2;
int currQuadColBegin;
int currQuadColEnd;
int rowIndex;
int colIndex;
for (int i = 0; i < 2; i++)
{
currQuadColBegin = 0;
currQuadColEnd = columns / 2;
for (int j = 0; j < 2; j++)
{
for (int t = 0; t < targets / 4; t++)
{
rowIndex = rand.Next(currQuadRowBegin, currQuadRowEnd);
colIndex = rand.Next(currQuadColBegin, currQuadColEnd);
while (Matrix[rowIndex, colIndex] != null)
{
rowIndex = rand.Next(currQuadRowBegin, currQuadRowEnd);
colIndex = rand.Next(currQuadColBegin, currQuadColEnd);
}
Matrix[rowIndex, colIndex] = new Element(TargetType);
}
currQuadColBegin = currQuadColEnd++;
currQuadColEnd = columns - 1;
}
currQuadRowBegin = currQuadRowEnd++;
currQuadRowEnd = rows - 1;
}
// Some targets may be unarranged yet (up to three)
int remainding = targets % 4;
while (remainding > 0)
{
rowIndex = rand.Next(0, rows);
colIndex = rand.Next(0, columns);
while (Matrix[rowIndex, colIndex] != null)
{
rowIndex = rand.Next(0, rows);
colIndex = rand.Next(0, columns);
}
Matrix[rowIndex, colIndex] = new Element(TargetType);
remainding--;
}
// Fill the remainding elements of the target matrix with other targets
List<int> fakeTargets = new List<int>(rows * columns - targets);
// If we are placing 10 targets in a 9x6 matrix then we need to place an extra
// 9 * 6 - 10 = 34 targets and if we have, say, 4 types then we can divide that
// between 4-1 (for the target type)
int targetsOfEachType = (rows * columns - targets) / types-1;
for (int i = 0; i < types; i++)
{
if (i == TargetType) continue;
for (int j = 0; j < targetsOfEachType; j++)
{
fakeTargets.Add(i);
}
}
int tmp;
while (fakeTargets.Count < rows * columns - targets)
{
tmp = rand.Next(types);
while (tmp == TargetType)
{
tmp = rand.Next(types);
}
fakeTargets.Add(tmp);
}
Shuffle(fakeTargets); // Assume this method shuffles the list of fakeTargets
tmp = 0;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
if (Matrix[i, j] != null) continue;
Matrix[i, j] = new Element(fakeTargets[tmp++]);
}
}
return Matrix;
}
Of course, I'm not claiming this is a good solution, just one that works for me at least for now. I'll leave some time so that someone can post a better answer or some corrections over mine before I check this as the answer.

Properly printing a 2D array?

Currently working on writing a Conways life in C# for class. I've been taking small steps to get a hang out the language and game programming in general and have hit a snag in printing my 2D char array. Currently I'm using GetLength - 1 to not go over the bound but it fails to print out the last chars in the array.
What my initial file looks like
+*++
++*+
****
After its read into placed into Char (i believe)
*
*
****
What ends up printed
*
**
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
namespace ConwaysLife
{
class Program
{
static char[,] universe;
static void bigBang(int h, int w, List<string> grid)
{
universe = new char[h,w];
int row = 0;
foreach (string line in grid)
{
for (int i = 0; i < line.Length; i++)
{
if (line.ToCharArray()[i] == '*')
{
universe[row, i] = '*';
}
}
row++;
}
}
//How I'm attempting to print out my 2D char array
static void offspring()
{
StringBuilder cellLine = new StringBuilder();
for (int y = 0; y < universe.GetLength(1)-1; y++)
{
for (int x = 0; x < universe.GetLength(0)-1; x++)
{
Console.Write(universe[y, x]);
}
Console.WriteLine();
}
//pause
Console.ReadLine();
}
static void Main(string[] args)
{
List<string> tempLine = new List<string>();
//Console.WriteLine("File Path?");
int width = 0;
int height = 0;
//read file into List
using (StreamReader r = new StreamReader("life.txt"))
{
while (r.Peek() >= 0)
{
tempLine.Add(r.ReadLine());
//compare current width to new width
if (tempLine[height].Length >= width) { width = tempLine[height].Length; }
//increase height when going to next row
height++;
}
bigBang(height, width, tempLine);
}
offspring();
}
}
}
Update Offspring()
static void offspring()
{
StringBuilder cellLine = new StringBuilder();
for (int x = 0; x <= universe.GetLength(1); x++)
{
for (int y = 0; y <= universe.GetLength(0); y++)
{
Console.Write(universe[x, y]);
}
Console.WriteLine();
}
//pause
Console.ReadLine();
}
You have an off-by-one error in your offspring function. Note that you're doing it correctly in the bigBang function.
You are looping while x < GetLength()-1. You just need x < GetLength(), because that excludes the case when x == GetLength().
An analagous loop:
for (i = 0; i < 4; i++)
Console.WriteLine(i);
Output:
0
1
2
3
I'm not familiar with the game principles, but there's a problem in your offspring method.
y < universe.GetLength(1)-1
This translates to y < 3 - 1 or y < 2, making your iteration go from y = 0 to 1.
To fix, simply remove the two occurences of -1.
for (int y = 0; y < universe.GetLength(1); y++)
{
for (int x = 0; x < universe.GetLength(0); x++)
{
In addition, you have your indices reversed when you access universe.
Console.Write(universe[y, x]);
There you're using the y variable to access the row, and x for the column. The inverse should be done like this:
Console.Write(universe[x, y]);
Giving a final output of
++*
*+*
+**
++*
While I'll delve deeper as to why it wasn't working as I expected it to I simply passed the sizes of the array when I created it to my offspring() and used those values when printing. Once that small change was the done the output came out as expected.
*
*
****

Browse a matrix

I want to browse a matrix like these one :
I want browse the first row, get the smallest number, then browse the row matching with the precedent smallest number.
Ex : I browse the A row : I browse the cell A,A , I get 0. I don't keep it (because it's 0) I browse the cell A,D I get 5. I keep it. I browse the cell A,G I get 8 but i don't keep it because it is superior to 5. I browse cell A,K and I get 4 I keep it (< 5).
For the moment it's ok, a simple loop is sufficient to do this. Then I want to browse the row K and if possible don't browse the cell K,A because I already browsed it when I browsed the row A.
You need to loop through an upper/lower half of the matrix? I assume a matrix is an array of int arrays.
var matrix = new int[][]{ ... };
int smallest = 0;
for(int i = 0; i < matrix.Length; i++)
{
for(int j = 0; j < matrix.Length; j++)
{
int number = matrix[i][j];
if (number != 0 && number < smallest)
smallest = number;
}
}
Although, I didn't quite get
then browse the row matching with the precedent smallest number
part.
Here the solution I found :
private static IEnumerable<int> ComputeMatrix(int[,] matrix)
{
// check args
if (matrix.Rank != 2) { throw new ArgumentException("matrix should have a rank of 2"); }
if (matrix.GetUpperBound(0) != matrix.GetUpperBound(1)) { throw new ArgumentException("matrix should have the same size");}
// indice treated
List<int> treatedIndex = new List<int>();
for (int i = 0; i <= matrix.GetUpperBound(0); i++)
{
if (treatedIndex.Count == matrix.GetUpperBound(0))
break;
// distance minimum between 2 points
int distanceMin = Int32.MaxValue;
// next iteration of index
int nextI = i;
// add the index to ignore in the next iteration
int nextJ = -1;
for (int j = 0; j <= matrix.GetUpperBound(1); j++)
{
if (treatedIndex.IndexOf(j) == -1)
{
if (matrix[i, j] != 0 && matrix[i, j] < distanceMin)
{
distanceMin = matrix[i, j];
nextI = j;
nextJ = i;
}
}
}
i = nextI - 1;
treatedIndex.Add(nextJ);
yield return distanceMin;
}
}

Categories

Resources