Help how to fill the 3x3 matrix with the same numbers in the same order. I can fill a two-dimensional array, but I don’t have to describe such filling rules.

Picture as an example:

3x3 matrix

This is how I fill in and withdraw normally, how can I fix this?

int[] number = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int[,] matrix = new int[3, 3]; int index = 0; for (int i = 0; i < matrix.GetLength(0); i++) for (int j = 0; j < matrix.GetLength(1); j++) { matrix[i, j] = number[index]; index++; } for (int i = 0; i < matrix.GetLength(0); i++) for (int j = 0; j < matrix.GetLength(1); j++) if (j == matrix.GetLength(1) - 1) Console.Write(matrix[i, j].ToString() + "\r\n"); else Console.Write( matrix[i, j].ToString() + "\t"); 
  • Clarify the question: the problem is to create a fill algorithm or program it? - Mikhail Grebenev
  • 2
    @MikhailGrebenev what's the difference, it's almost the same - tym32167

5 answers 5

For example:

 const int max = 3; int[,] matrix = new int[max, max]; int curr = 1; for (int diff = 1 - max; diff <= max - 1; diff++) { for (int i = 0; i < max; i++) { int j = i - diff; if (j < 0 || j >= max) continue; matrix[i, j] = curr++; } } 

Checking:

 for (int i = 0; i < max; i++) { for (int j = 0; j < max; j++) Console.Write(matrix[i, j] + " "); Console.WriteLine(); } 

Result:

 4 2 1 7 5 3 9 8 6 

Explanation: In the cells of each diagonal, the difference of the coordinates y and x constant. The minimum difference for the “uppermost” diagonal is that there is only a cell (max - 1, 0) , the difference is 1 - max . The minimum difference for the “lowest” diagonal, in which the cell (0, max - 1) is, of course, max - 1 . The outer loop on these same diagonals. One difference - one diagonal.

Then, in each diagonal, we loop through the x coordinate (denoted as i in the code). It can be from 0 to max - 1 . But for example, for the first diagonal, not all x possible, since there is only one element in it. Therefore, we act like this: we calculate x , having the difference y - x == diff , we calculate y (in code j ). We check that y falls between 0 and max - 1 .

In each cell found we write the following number. The current number is stored, of course, in the variable curr , and is incremented by one after each entry in the matrix.

  • A little bit ahead :) - tym32167
  • @ tym32167: The code is essentially the same, right? - VladD
  • :) Well, the idea is exactly the same - tym32167
  • @ tym32167: You have a diff in the other direction, and so identical. Great minds think alike :) - VladD

As an option

 var matr = new int[3,3]; var cnt = 0; for(var y=2; y>=-2; y--) for(var x=0; x<3; x++) if((y+x) >= 0 && (y+x)<3) matr[x, y+x] = ++cnt; 

check

 for (var i = 0; i < 3; i++) { for (var j = 0; j < 3; j++) Console.Write($"{matr[i, j]} "); Console.WriteLine(); } 

Conclusion

 4 2 1 7 5 3 9 8 6 

    Naive implementations were dismantled before me, well ... If you look closely, you can notice some similarity of the desired order of filling the array with the search in width, use this and get the following solution:

     class Program { static void Main(string[] args) => new Program().Run(); const int dim = 10; int[,] matrix = new int[dim, dim]; Queue<(int, int)> queue = new Queue<(int, int)>(); void Run() { Fill(); Print(); } void Fill() { int index = 0; queue.Enqueue((dim - 1, 0)); while (queue.Count > 0) { var (x, y) = queue.Dequeue(); matrix[x, y] = ++index; if (x > 0) EnqueueIfNotUsed(x - 1, y); if (y < dim - 1) EnqueueIfNotUsed(x, y + 1); } } void EnqueueIfNotUsed(int x, int y) { if (matrix[x, y] == 0 && !queue.Contains((x, y))) queue.Enqueue((x, y)); } void Print() { var width = (dim * dim).ToString().Length + 1; for (int y = 0; y < dim; y++) { for (int x = 0; x < dim; x++) Console.Write(matrix[x, y].ToString().PadLeft(width)); Console.WriteLine(); } Console.ReadKey(); } } 

      Here is my option. It is curious that it actually fills it with a snake and this is especially clearly seen if there is not enough data in the input array to completely fill the square and, under debugging:

      0 0 0 10
      0 0 0 0
      0 0 0 0
      0 0 0 0

      0 0 20 10
      0 0 0 0
      0 0 0 0
      0 0 0 0

      0 0 20 10
      0 0 0 31
      0 0 0 0
      0 0 0 0

      0 44 20 10
      0 0 0 31
      0 0 0 0
      0 0 0 0

      0 44 20 10
      0 0 55 31
      0 0 0 0
      0 0 0 0

      The code itself:

       void Main() { const int max = 4; int[] numbers = { 10, 20, 31, 44, 55, 66, 77, 88, 90, 91, 92, 93, 94, 95, 96, 97 }; var result = this.Putty(max, numbers); PrettyPrint(result, max); } // Define other methods and classes here public int[,] Putty(int size, int[] numbers) { int[,] matrix = new int[size, size]; int x = 0; int y = size - 1; int turnAbove = 0; int turnBelow = 0; var iter = numbers.GetEnumerator(); while (iter.MoveNext()) { matrix[x, y] = (int)iter.Current; PrettyPrint(matrix, size); x++; y++; if (x >= size && y >= size) { turnBelow++; y = 0; x = turnBelow; } else if (y >= size) { turnAbove++; x = 0; y = size - 1 - turnAbove; } else if (x >= size) { turnBelow++; y = 0; x = turnBelow; } } return matrix; } public void PrettyPrint(int[,] matrix, int max) { Console.WriteLine(); for (int i = 0; i < max; i++) { for (int j = 0; j < max; j++) Console.Write(matrix[i, j] + " "); Console.WriteLine(); } } 

      If your input numbers are not in order - the very algorithm, O (n)

      The basis of the algorithm is the transition from the current cell x, y diagonally through the simultaneous increment of x and y.

      Next you need to write the conditions for determining that we jumped over the edge of the array.

      I counted three variants of departure: over the diagonal, when we flew beyond the vertical border; under the diagonal, when flew over the horizontal border and on the diagonal (flew simultaneously over both borders).

      Probably, you can try to optimize the algorithm (reduce the number of auxiliary variables or condition branches), leaving room for creativity.

      I also did not take into account the option when we have an array completely filled, and the input IEnumerable is not over yet.

        And let's just calculate the value of these indices.

        Above the diagonal is simple: count the elements in the previous diagonals (the sum of the arithmetic progression), and add the number in the current diagonal. And in order not to think that there is under the diagonal, we use symmetry.

        Total:

         static int GetValue(int i, int j, int max) { if (i <= j) { int d = (i - j) + max - 1; // номер диагонали int s = d * (d + 1) / 2; // сумма предыдущих диагоналей return s + i + 1; // i = наш номер в диагонали } else { return max * max + 1 - GetValue(max - 1 - i, max - 1 - j, max); } } 

        The main code becomes trivial:

         const int max = 3; int[,] matrix = new int[max, max]; for (int i = 0; i < max; i++) for (int j = 0; j < max; j++) matrix[i, j] = GetValue(i, j, max); 

        The result, of course, is the same.