Search code examples
algorithmdelphimatrixdelphi-xe2spiral

Matrix and algorithm "spiral"


i wanted ask if there some algorithm ready, that allowed me to do this: i have a matrix m (col) x n (row) with m x n elements. I want give position to this element starting from center and rotating as a spiral, for example, for a matrix 3x3 i have 9 elements so defined:

 5  6  7
 4  9  8
 3  2  1 

or for una matrix 4 x 3 i have 12 elements, do defined:

  8   9  10  1
  7  12  11  2
  6   5   4  3

or again, a matrix 5x2 i have 10 elements so defined:

    3  4
    7  8
   10  9
    6  5 
    2  1

etc. I have solved basically defining a array of integer of m x n elements and loading manually the value, but in generel to me like that matrix maked from algorithm automatically. Thanks to who can help me to find something so, thanks very much.

UPDATE

This code, do exactely about i want have, but not is in delphi; just only i need that start from 1 and not from 0. Important for me is that it is valid for any matrics m x n. Who help me to translate it in delphi?

(defun spiral (rows columns)  
  (do ((N (* rows columns))       
    (spiral (make-array (list rows columns) :initial-element nil))      
    (dx 1) (dy 0) (x 0) (y 0)    
   (i 0 (1+ i)))     
 ((= i N) spiral)   
 (setf (aref spiral y x) i)
    (let ((nx (+ x dx)) (ny (+ y dy)))  
    (cond       
       ((and (< -1 nx columns)       
       (< -1 ny rows)           
       (null (aref spiral ny nx)))    
    (setf x nx 
          y ny))  
     (t (psetf dx (- dy)                 
       dy dx)       
    (setf x (+ x dx)             
     y (+ y dy))))))) 


> (pprint (spiral 6 6))

#2A ((0  1  2  3  4  5)
    (19 20 21 22 23  6)
    (18 31 32 33 24  7)
    (17 30 35 34 25  8)
    (16 29 28 27 26  9)
    (15 14 13 12 11 10))


> (pprint (spiral 5 3))

#2A  ((0  1 2)
     (11 12 3)
     (10 13 4)
      (9 14 5)
      (8 7 6))

Thanks again very much.


Solution

  • Based on the classic spiral algorithm. supporting non-square matrix:

    program SpiralMatrix;
    {$APPTYPE CONSOLE}
    uses
      SysUtils;
    
    type
      TMatrix = array of array of Integer;
    
    procedure PrintMatrix(const a: TMatrix);
    var
      i, j: Integer;
    begin
      for i := 0 to Length(a) - 1 do
      begin
        for j := 0 to Length(a[0]) - 1 do
          Write(Format('%3d', [a[i, j]]));
        Writeln;
      end;
    end;
    
    var
      spiral: TMatrix;
      i, m, n: Integer;
      row, col, dx, dy,
      dirChanges, visits, temp: Integer;
    begin
      m := 3; // columns
      n := 3; // rows
      SetLength(spiral, n, m);
      row := 0;
      col := 0;
      dx := 1;
      dy := 0;
      dirChanges := 0;
      visits := m;
      for i := 0 to n * m - 1 do
      begin
        spiral[row, col] := i + 1;
        Dec(visits);
        if visits = 0 then
        begin
          visits := m * (dirChanges mod 2) + n * ((dirChanges + 1) mod 2) - (dirChanges div 2) - 1;
          temp := dx;
          dx := -dy;
          dy := temp;
          Inc(dirChanges);
        end;
        Inc(col, dx);
        Inc(row, dy);
      end;
      PrintMatrix(spiral);
      Readln;
    end.
    

    3 x 3:

    1  2  3
    8  9  4
    7  6  5
    

    4 x 3:

     1  2  3  4
    10 11 12  5
     9  8  7  6
    

    2 x 5:

     1  2
    10  3
     9  4
     8  5
     7  6