Rotating a Matrix clockwise in c# - c#

I'm trying to rotate a multi-dimensional array clockwise.
Here's my code.
I've already got the transpose part down but I need help with the reverse section.
I've tried multiple solution but they just don't work with the code I already have so, yeah. Thank you.
Desired output
7 4 1
8 5 2
9 6 3
static void RotateMatrix()
{
// Multidimenonsal array to rotate
int[,] matrix = new int[,]
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// Swaps places -- transpose
/*
Output of this for loop
{
1 4 7
2 5 8
3 6 9
}
*/
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
var temp = matrix[i, j]; // store matrix(pos x, pos y) in temp var
matrix[i, j] = matrix[j, i]; // set the position matrix(pos x, pos y) to (opposite position)
matrix[j, i] = temp; // set (opposite position) to temp var
}
}
// Reverse !! Need help Here!!
// Prints out the rotated matrix
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write(matrix[j, i]);
}
Console.WriteLine();
}
}

Rotating a matrix in place will be quite challenging. I would highly recommend just creating a new matrix, especially when dealing with small matrices. You will also need to reverse the direction in one of the index operations:
var result = new int[3,3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
result[j, 2-i] = matrix[i, j];
}
}
However, unless you are doing this for learning I would suggest using a pre-existing matrix library, it will likely both have more features and be faster.
For example, you made one of the classic blunders when working with multidimensional matrices and call matrix.GetLength(...) for each iteration, this method is fairly slow, so you should be getting the length outside the loop and storing it.

Related

moving an element in 2d array with arrow keys and having border restricting movement

I dont know if this has been answered before but how would I move an element in 2d array with arrow keys? say something like this and having it not move if it is not possible as in the image displayed 0 can swap and go up, down, left and right but the next move you are restricted to just three options as up,down and left only
New to c# so if there are helpful examples online about my problem just post them down the comment
using System;
namespace moveElement
{
public class move
{
static void Main(string[] args)
{
int[,] arr = { { 9, 1, 4 }, { 5, 0, 3 }, { 6, 8, 2 } };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write(arr[i, j] + " ");
}
Console.WriteLine();
}
}
}
}
Took what was suggested and made it work somehow like this
ConsoleKeyInfo info = Console.ReadKey();
if (info.Key == ConsoleKey.RightArrow)
{
int temp = arr[1, 1];
arr[1, 1] = arr[1, 2];
arr[1, 2] = temp;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write(arr[i, j] + " ");
}
Console.WriteLine();
}
}
After working on the code for sometime I get error "use of unassigned local variable x and y" on line 41(y) and 47(x) I have completed most of the problem but stuck on this error
using System;
namespace moveElement
{
public class move
{
static void Main(string[] args)
{
int x, y;
int[,] arr = { { 0, 1, 4 }, { 3, 9, 5 }, { 6, 8, 2 } };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write(arr[i, j] + " ");
Solved the problem by giving x and y a value of 0.
You could try something similar to the answer of this post where you take the variable of position 1, put it in a temp variable, then set position 1 to the value of position 2 and finally set the value of position 2 to what is in the temp variable:
var t = a;
a = b;
b = t;
To actually figure out if you can move in a specific direction, you will need to check if you are at a boundary, for example, the boundaries would be (where i is any valid position):
arr[0, i]
arr[arr.getLength(0)-1, i]
arr[i, 0]
arr[i, arr.getLength(1)-1]
if your current position is the same as one of those, you will need to add some conditions so that you cant move in a specific direction, for example, if you have arr[0, i], you cannot move up one as it will then go to arr[-1, i] which does not exist.
I would suggest reading up on the Array.getLength(Int32 dimension) method for finding the boundaries (it essentially gets the length of the array at a specified dimension)

How to set a maximum value of string that can be shown in a matrix?

I'm trying to make a matrix that will show the string s only if it it displays a number less than 10. It would probably be easier doing this with an integer instead of the string but it doesn't show the same 8x8(or any other combination) the same because the "string.Empty" seems to be being the key(if someone could explain that part too, it would help me).
I also want to know how to display lets say letter "a" in the whole matrix, so that if the matrix is 3x3 I see 3 "a" in 3 rows.
Code here shows me matrix which lets s go over 10 which makes it not looking like a square.
string s = "";
int[,] matrix = new int[8, 8];
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
s += matrix[i, j] = i + j;
}
Console.WriteLine(s);
s = string.Empty;
}

How to build a large 2d array out of many smaller 2d arrays

I am trying to work towards a
512 x 512 (262144 elements)
I currently have a
List<double[,]> data;
Dimensions are:
4096 x [8 , 8] (262144 elements)
The 2d array I am working towards is square.
List<List<float>> newList = new List<List<float>(); //working towards
I have tried something along the lines of:
for (int i = 0; i < Math.Sqrt(data.Count); i++ ) {
List<float> row = new List<float>();
foreach (double[,] block in data) {
for (int j = 0; j < 8; j++) {
row.Add(block[i,j]); //i clearly out of range
}
}
newList.Add(row);
}
What I was trying to do there was to brute force my way and add up every row (which is 8 in length) and then add the large rows to the newList.
I believe you can do that in the following way
var newList = new List<List<float>>();
for (int i = 0; i < 512; i++)
{
var innerList = new List<float>();
for (int j = 0; j < 512; j++)
{
int x =(i/8)*64 + (j/8);
int y = i % 8;
int z = j % 8;
innerList.Add(data[x][y,z]);
}
newList.Add(innerList);
}
Basically you have 64x64 of your 8x8 blocks. So the (i,j) coordinate of the larger 512x512 structure translate in the following ways. First to determine the 8x8 block you have to figure out the row and column of the 64x64 structure of blocks by dividing the i and j by the size of the block (8) then you multiply the row (i/8) by the number of block in a row (64) and add the column (j/8). For the y and z it's simpler because you know that its just a matter of the remainder of i and j when divided by 8 (i%8) and (j%8).

filling multidimensional array with unique numbers in C#

I'm trying to write a code that will fill array with unique numbers.
I could write the code separately for 1, 2 and 3 dimensional arrays but number of for cycles grow to "infinity".
this is the code for 2D array:
static void fillArray(int[,] array)
{
Random rand = new Random();
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
array[i, j] = rand.Next(1, 100);
for (int k = 0; k < j; k++)
if (array[i, k] == array[i, j])
j--;
}
}
print_info(array);
}
Is it possible to do something like this for n-dimensional arrays?
My approach is to start with a 1-d array of unique numbers, which you can shuffle, and then slot into appropriate places in your real array.
Here is the main function:
private static void Initialize(Array array)
{
var rank = array.Rank;
var dimensionLengths = new List<int>();
var totalSize = 1;
int[] arrayIndices = new int[rank];
for (var dimension = 0; dimension < rank; dimension++)
{
var upperBound = array.GetLength(dimension);
dimensionLengths.Add(upperBound);
totalSize *= upperBound;
}
var singleArray = new int[totalSize];
for (int i = 0; i < totalSize; i++) singleArray[i] = i;
singleArray = Shuffle(singleArray);
for (var i = 0; i < singleArray.Length; i++)
{
var remainingIndex = i;
for (var dimension = array.Rank - 1; dimension >= 0; dimension--)
{
arrayIndices[dimension] = remainingIndex%dimensionLengths[dimension];
remainingIndex /= dimensionLengths[dimension];
}
// Now, set the appropriate cell in your real array:
array.SetValue(singleArray[i], arrayIndices);
}
}
The key in this example is the array.SetValue(value, params int[] indices) function. By building up the correct list of indices, you can use this function to set an arbitrary cell in your array.
Here is the Shuffle function:
private static int[] Shuffle(int[] singleArray)
{
var random = new Random();
for (int i = singleArray.Length; i > 1; i--)
{
// Pick random element to swap.
int j = random.Next(i); // 0 <= j <= i-1
// Swap.
int tmp = singleArray[j];
singleArray[j] = singleArray[i - 1];
singleArray[i - 1] = tmp;
}
return singleArray;
}
And finally a demonstration of it in use:
var array1 = new int[2,3,5];
Initialize(array1);
var array2 = new int[2,2,3,4];
Initialize(array2);
My strategy assigns sequential numbers to the original 1-d array to ensure uniqueness, but you can adopt a different strategy for this as you see fit.
You can use Rank property to get the total number of dimentions in your array
To insert use SetValue method
In the first two for loops you are analysing the array properly (i and j go from the start to the end of the corresponding dimension). The problem comes in the most internal part where you introduce a "correction" which actually provokes an endless loop for j.
First iteration:
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
Second iteration
- First loop: i = 0;
- Second loop: j = 0;
- Third loop: j = -1
. etc., etc.
(I start my analysis in the moment when the internal loop is used for the first time. Also bear in mind that the exact behaviour cannot be predicted as far as random numbers are involved. But the idea is that you are making the j counter back over and over by following an arbitrary rule).
What you want to accomplish exactly? What is this last correction (the one provoking the endless loop) meant to do?
If the only thing you intend to do is checking the previously stored values, you have to rely on a different variable (j2, for example) which will not affect any of the loops above:
int j2 = j;
for (int k = 0; k < j2; k++)
if (array[i, k] == array[i, j2])
j2--;

Concatenate a 2D array

I have two arrays mat1 & Mat2.
I want to have new_mat=[ma1,mat2];
I have written a function which works. I wonder if there is an efficient function for very large matrix or How can I do it with Array.CopyTo method.
public static double[,] Concatenate_matrix_byCol(double[,] Mat1, double[,] Mat2)
{
int col1=Mat1.GetLength(1);
int col2 = Mat2.GetLength(1);
int row1=Mat1.GetLength(0);
int row2 = Mat2.GetLength(0);
int i, j, y;
double[,] newMat = new double[row1, col1 + col2];
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
{
newMat[i, j] = Mat1[i, j];
}
}
for (i = 0; i < row1; i++)
{
for (y = 0; y < col2; y++)
{
newMat[i, y+col1] = Mat2[i, y];
}
}
return newMat;
}
You could combine your loops into:
for (i = 0; i < row1; i++)
{
for (j = 0; j < col1; j++)
newMat[i, j] = Mat1[i, j];
for (y = 0; y < col2; y++)
newMat[i, y+col1] = Mat2[i, y];
}
And maybe use pointers instead (test performance first!) but a library would properly be the best solution. That way you don't have to do micro-optimizations yourself.
There is a lot of libraries for .Net mentioned in this thread: Matrix Library for .NET
Depending on your performance requirement you could also look into parallel algorithms and you may be inspired by http://innovatian.com/2010/03/parallel-matrix-multiplication-with-the-task-parallel-library-tpl/. Again, a well-build library probably already have parallel algorithms.
When moving Arrays, you should look into Array.CopyTo instead of moving the cells one by one.
Also you could create a class that accepts the 2 matrices, and provides a level of abstraction that makes them look like 1 matrix but just keeps them seperate underneath.
For instance M1 = 20x 30 and M2 = 25 x 30 so you have a class M3 that 'looks like' M1 + M2, a 55 x 30 matrix.
When someone asks for M3[28, 23] this class will know that it should redirect to M2[8, 23] because M1 was only 20 positions wide (28-20=8). That way you don't have to copy the memory, that's expensive. Figuring out how to reroute a request to the right matrix is much cheaper. Depends on how much the matrix accessed afterwards obviously.
edit
This is what I mean:
class Program {
static void Main(string[] args) {
int[,] x = { { 1, 2, 3 }, { 4, 5, 6 } };
int[,] y = { { 7, 8, 9 }, { 10, 11, 12 } };
var xy = new StitchMatrix<int>(x, y);
Console.WriteLine("0,0=" + xy[0, 0]); // 1
Console.WriteLine("1,1=" + xy[1, 1]); // 5
Console.WriteLine("1,2=" + xy[1, 2]); // 6
Console.WriteLine("2,2=" + xy[2, 2]); // 9
Console.WriteLine("3,2=" + xy[3, 2]); // 12
}
}
class StitchMatrix<T> {
private T[][,] _matrices;
private int[] _lengths;
public StitchMatrix(params T[][,] matrices) {
// TODO: check they're all same size
_matrices = matrices;
// call uperbound once for speed
_lengths = _matrices.Select(m => m.GetUpperBound(0)).ToArray();
}
public T this[int x, int y] {
get {
// find the right matrix
int iMatrix = 0;
while (_lengths[iMatrix] < x) {
x -= (_lengths[iMatrix] + 1);
iMatrix++;
}
// return value at cell
return _matrices[iMatrix][x, y];
}
}
}
Regards Gert-Jan

Categories