Print 2-D Array in clockwise expanding spiral from center

前端 未结 4 1866
离开以前
离开以前 2020-12-02 00:18

I have an guaranteed to be a perfect square matrix. I want to start at the center of the matrix in this case it would be matrix[2][2], I know h

相关标签:
4条回答
  • 2020-12-02 01:02
    bool IsIterationComplete(int iteration, int nCenter, std::vector<std::vector<bool>>& vVisited)
    {
        int nHigh = nCenter+iteration;
        int nLow = nCenter-iteration;
        //cout<<endl<<"High "<<nHigh<<"Low "<<nLow<<endl;
        for(int i=nLow;i<=nHigh;i++)
        {
            if(!vVisited[nHigh][i] || !vVisited[nLow][i]) 
                return false;
        }
    
        for(int i=nLow;i<=nHigh;i++)
        {
            if(!vVisited[i][nHigh] || !vVisited[i][nLow])
                return false;
        }
    
        return true;
    }
    void PrintSpiral(std::vector<std::vector<int>>& vMat,std::vector<std::vector<bool>>& vVisited, int row, int col, int nCenter, int iteration)
    {
        cout<<vMat[row][col];
        vVisited[row][col]=true;
    
        if(row==0 && col==0)
            return;
    
        if(IsIterationComplete(iteration,nCenter,vVisited))
            iteration++;
    
        //cout<<endl<<"row "<<row<<" column "<<col<<"Iteration "<<iteration<<endl;
    
    //left
        if(col-1>=0 && !vVisited[row][col-1] && col-1>=nCenter-iteration)
        {
            cout<<"Left "<<endl;
            PrintSpiral(vMat,vVisited,row,col-1,nCenter,iteration);
        }
    
        //Down
        if((row+1)<vMat.size() && !vVisited[row+1][col] && row+1<=nCenter+iteration)
        {
            cout<<"Down "<<endl;
            PrintSpiral(vMat,vVisited,row+1,col,nCenter,iteration);
        }
    
        //right
        if((col+1)<vMat.size() && !vVisited[row][col+1] && col+1<=nCenter+iteration)
        {
            cout<<"Right "<<endl;
            PrintSpiral(vMat,vVisited,row,col+1,nCenter,iteration);
        }
    
        //up    
        if(row-1>=0 && !vVisited[row-1][col] && row-1>=nCenter-iteration)
        {
            cout<<"Up "<<endl;
            PrintSpiral(vMat,vVisited,row-1,col,nCenter,iteration);
        }
    }
    
    
    int main (int argc, const char * argv[])
    {
        int nCount=1;
        std::vector<std::vector<int>> vMat;
        std::vector<std::vector<bool>> vVisited;
        for(int i=0; i<7; i++)
        {
            std::vector<int> row;
            std::vector<bool> visitedRow;
            for(int j=0; j<7; j++)
            {
                row.push_back(nCount);
                cout<<nCount<<'\t';
                nCount++;
                visitedRow.push_back(false);
            }
            cout<<'\n';
            vMat.push_back(row);
            vVisited.push_back(visitedRow);
        }
        cout<<'\n';
        PrintSpiral(vMat,vVisited,vMat.size()/2,vMat.size()/2,vMat.size()/2,0);
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-02 01:13

    As this smells like homework then no code or direct answer instead just few hints:

    You can look at this as an turtle problem:

    Let m be movement by 1 cell and r be rotation by 90 degrees in your spiral direction (CW or CCW). then the spiral can be encoded as series of turtle commands forming this pattern (from the start point):

        m,r,m,r, 
        m,m,r,m,m,r,
        m,m,m,r,m,m,m,r,
        m,m,m,m,r,m,m,m,m,r,
        m,m,m,m,m,r 
    

    As you can see you start with 1x move then rotate after two repetition you switch to 2x move, after 2 moves switch to 3x move,... and so on. This can be done with just few for loops (or just by one with some proper iterations and stopping when matrix number of cells is hit ... or the endpoint corner is hit)

    You need to handle even/odd matrix sizes

    for odd matrix sizes is the middle point easy. For even sizes it is a bit more complicated. if you use CW rotation then use the rounded down division result of halving the size and start with moving to the right. (if you need different spiral then you need to add +1 to x and/or y and change starting direction) so the spiral will stay centered.

    So If you got even sized matrix then the last movement is twice if you got odd size then the last movement is there just once (like in this example)

    rotation

    Have direction stored as 2D vector. for example d=(+1,0) means right. to rotate 2D vector you just swap coordinates and negate one axis (which one means the CW/CCW). For example (x,y) -> (y,-x)

    movement

    Store current position as 2D vector too. The movement is just adding current direction vector to it.

    Have fun with solving this ...

    0 讨论(0)
  • 2020-12-02 01:16

    Let's identify the patterns first ..

    Even-Size Square Matrix, Example: 4x4

      07 > 08 > 09 > 10
      ^               v
      06  (01)> 02   11
      ^          v    v
      05 < 04 < 03   12
                      v
     [16]< 15 < 14 < 13
    
    Starting Point: [2, 2] ~ [SIZE/2, SIZE/2]
    
    Ending Point: [4, 1] ~ [SIZE, 1]
    
    Chains: Count(K-chain)=2 for K = 1..(SIZE-2)
            + 3 for Count = SIZE-1
    

    Odd-Size Square Matrix, Example: 5x5

      21 > 22 > 23 > 24 >[25]
      ^
      20   07 > 08 > 09 > 10
      ^    ^               v
      19   06  (01)> 02   11
      ^    ^          v    v
      18   05 < 04 < 03   12 
      ^                    v
      17 < 16 < 15 < 14 < 13
    
    Starting Point: [2, 2] ~ [⌊SIZE/2⌋, ⌊SIZE/2⌋]
    
    Ending Point: [1, 5] ~ [1, SIZE]
    
    Chains: Count(K-chain)=2 for K = 1..(SIZE-2)
            + 3 for Count = SIZE-1
    

    Live Code

    void print_spiral (int ** matrix, int size)
    {
        int x = 0; // current position; x
        int y = 0; // current position; y
        int d = 0; // current direction; 0=RIGHT, 1=DOWN, 2=LEFT, 3=UP
        int c = 0; // counter
        int s = 1; // chain size
    
        // starting point
        x = ((int)floor(size/2.0))-1;
        y = ((int)floor(size/2.0))-1;
    
        for (int k=1; k<=(size-1); k++)
        {
            for (int j=0; j<(k<(size-1)?2:3); j++)
            {
                for (int i=0; i<s; i++)
                {
                    std::cout << matrix[x][y] << " ";
                    c++;
    
                    switch (d)
                    {
                        case 0: y = y + 1; break;
                        case 1: x = x + 1; break;
                        case 2: y = y - 1; break;
                        case 3: x = x - 1; break;
                    }
                }
                d = (d+1)%4;
            }
            s = s + 1;
        }
    }
    
    0 讨论(0)
  • 2020-12-02 01:19
        int radius = 0;
        int i = centerX;
        int j = centerY;
        Debug.Log("i=" + i + "; j=" + j);
        ++i;
        radius += 2;
        while ((i < dimm) && (i >= 0))
        {
            for (int c = j; j < c + radius; j++)
                Debug.Log("i=" + i + "; j=" + j);
            --j;
            --i;
            for (int c = i; i > c - radius + 1; i--)
                Debug.Log("i=" + i + "; j=" + j);
            if (i < 0)
                break;
            else
                Debug.Log("i=" + i + "; j=" + j);
            --j;
            for (int c = j; j > c - radius; j--)
                Debug.Log("i=" + i + "; j=" + j);
            ++i;
            ++j;
            for (int c = i; i < c + radius; i++)
                Debug.Log("i=" + i + "; j=" + j);
            radius += 2;
        }
    

    This Code will output counterclockwise squared matrix (dimm X dimm) indexes from custom center(CenterX, CenterY); and end up, if it came out of matrix size.

    0 讨论(0)
提交回复
热议问题