square puzzle solution

前端 未结 5 950
一生所求
一生所求 2021-01-01 02:51

Question: given an integer number n, print the numbers from 1 up to n2 like this:

n = 4

result is:

01 02 03 04
12 13 14 05
11 16 1         


        
相关标签:
5条回答
  • 2021-01-01 03:23

    Here's a different approach. It relies on spotting that the movements you make cycle between: right, down, left, up, right, .... Further, the number of times you move goes: 3 right, 3 down, 3 left, 2 up, 2 right, 1 down, 1 left. So without further ado, I will code this up in Python.

    First, I will use some itertools and some numpy:

    from itertools import chain, cycle, imap, izip, repeat
    from numpy import array
    

    The directions cycle between: right, down, left, up, right, ...:

    directions = cycle(array(v) for v in ((0,1),(1,0),(0,-1),(-1,0)))
    

    (I'm using numpy's arrays here so I can easily add directions together. Tuples don't add nicely.)

    Next, the number of times I move counts down from n-1 to 1, repeating each number twice, and the first number three times:

    countdown = chain((n-1,), *imap(repeat, range(n-1,0,-1), repeat(2)))
    

    So now my sequence of directions can be created by repeating each successive direction by the paired number in countdown:

    dirseq = chain(*imap(repeat, directions, countdown))
    

    To get my sequence of indices, I can just sum this sequence, but (AFAIK) Python does not provide such a method, so let's quickly throw one together:

    def sumseq(seq, start=0):
      v = start
      yield v
      for s in seq:
        v += s
        yield v
    

    Now to generate the original array, I can do the following:

    a = array(((0,)*n,)*n) # n-by-n array of zeroes
    for i, v in enumerate(sumseq(dirseq, array((0,0)))):
      a[v[0], v[1]] = i+1
    print a
    

    Which, for n = 4, gives:

    [[ 1  2  3  4]
     [12 13 14  5]
     [11 16 15  6]
     [10  9  8  7]]
    

    and, for n = 5, gives:

    [[ 1  2  3  4  5]
     [16 17 18 19  6]
     [15 24 25 20  7]
     [14 23 22 21  8]
     [13 12 11 10  9]]
    

    This approach can be generalised to rectangular grids; I leave this as an exercise for the reader ;)

    0 讨论(0)
  • 2021-01-01 03:34

    Though your example is in python and this is in Java, I think you should be able to follow the logic:

    public class SquareTest {
    
    public static void main(String[] args) {
        SquareTest squareTest = new SquareTest(4);
        System.out.println(squareTest);
    }
    
    private int squareSize;
    private int[][] numberSquare;
    private int currentX;
    private int currentY;
    private Direction currentDirection;
    
    private enum Direction {
        LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP;
    };
    
    public SquareTest(int squareSize) {
        this.squareSize = squareSize;
        numberSquare = new int[squareSize][squareSize];
        currentY = 0;
        currentX = 0;
        currentDirection = Direction.LEFT_TO_RIGHT;
        constructSquare();
    }
    
    private void constructSquare() {
        for (int i = 0; i < squareSize * squareSize; i = i + 1) {
            numberSquare[currentY][currentX] = i + 1;
            if (Direction.LEFT_TO_RIGHT.equals(currentDirection)) {
                travelLeftToRight();
            } else if (Direction.RIGHT_TO_LEFT.equals(currentDirection)) {
                travelRightToLeft();
            } else if (Direction.TOP_TO_BOTTOM.equals(currentDirection)) {
                travelTopToBottom();
            } else {
                travelBottomToTop();
            }
        }
    }
    
    private void travelLeftToRight() {
        if (currentX + 1 == squareSize || numberSquare[currentY][currentX + 1] != 0) {
            currentY = currentY + 1;
            currentDirection = Direction.TOP_TO_BOTTOM;
        } else {
            currentX = currentX + 1;
        }
    }
    
    private void travelRightToLeft() {
        if (currentX - 1 < 0 || numberSquare[currentY][currentX - 1] != 0) {
            currentY = currentY - 1;
            currentDirection = Direction.BOTTOM_TO_TOP;
        } else {
            currentX = currentX - 1;
        }
    }
    
    private void travelTopToBottom() {
        if (currentY + 1 == squareSize || numberSquare[currentY + 1][currentX] != 0) {
            currentX = currentX - 1;
            currentDirection = Direction.RIGHT_TO_LEFT;
        } else {
            currentY = currentY + 1;
        }
    }
    
    private void travelBottomToTop() {
        if (currentY - 1 < 0 || numberSquare[currentY - 1][currentX] != 0) {
            currentX = currentX + 1;
            currentDirection = Direction.LEFT_TO_RIGHT;
        } else {
            currentY = currentY - 1;
        }
    }
    
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < squareSize; i = i + 1) {
            for (int j = 0; j < squareSize; j = j + 1) {
                builder.append(numberSquare[i][j]);
                builder.append(" ");
            }
            builder.append("\n");
        }
    
        return builder.toString();
    }
    }
    
    0 讨论(0)
  • 2021-01-01 03:39

    Another way to do it, this time in C#:

    int number = 9;
    var position = new { x = -1, y = 0 };
    var directions = new [] { 
        new { x = 1, y = 0 },
        new { x = 0, y = 1 },
        new { x = -1, y = 0 },
        new { x = 0, y = -1 }
    };
    
    var sequence = (
        from n in Enumerable.Range(1, number)
        from o in Enumerable.Repeat(n, n != number ? 2 : 1)
        select o
    ).Reverse().ToList();
    
    var result = new int[number,number];
    
    for (int i = 0, current = 1; i < sequence.Count; i++)
    {
        var direction = directions[i % directions.Length];      
    
        for (int j = 0; j < sequence[i]; j++, current++)
        {
            position = new {
                x = position.x + direction.x,
                y = position.y + direction.y
            };
    
            result[position.y, position.x] = current;
        }
    }
    
    0 讨论(0)
  • 2021-01-01 03:41

    I have solved your problem using C++. I don't know if it will be helpful for you. But posting it. If it works for you it will be a pleasure.

    Here is the Code:

        #include<iostream>
        #include<string.h>
        using namespace std;
    
        bool valid(int n,int r,int c)
        {
            if(r>=1 && r<=n && c>=1 && c<=n)
                return true;
            return false;
        }
    
    
        int main()
        {
            pair<int,int>d1,d2,d3,d4,temp;
            d1 = make_pair(0,1);
            d2 = make_pair(1,0);
            d3 = make_pair(0,-1);
            d4 = make_pair(-1,0);
            /**********************direction******************************/
    
            int n, i, j, counter=1, newR = 1, newC = 0, direction = 4;
            bool changeDir=true;
            /**************************variables*************************/
    
            cin>>n;
            int arr[n+1][n+1];
            int visited[n+1][n+1];
            /*************************arrays********************************/
    
            memset(visited,0,sizeof(visited));
            memset(arr,0,sizeof(arr));
            /***************initializing the array**************************/
    
            while(counter<=n*n)
            {
                if(direction==1 && changeDir)
                {
                    temp = make_pair(d2.first,d2.second);
                    direction=2;
                    changeDir=false;
                }
                else if(direction==2&& changeDir)
                {
                    temp = make_pair(d3.first,d3.second);
                    direction=3;
                    changeDir=false;
                }
                else if(direction==3&& changeDir)
                {
                    temp = make_pair(d4.first,d4.second);
                    direction=4;
                    changeDir=false;
                }
                else if(direction==4&& changeDir)
                {
                    temp = make_pair(d1.first,d1.second);
                    direction=1;
                    changeDir=false;
                }
                while(counter<=(n*n) && !changeDir)
                {
                    newR =newR+temp.first;
                    newC=newC+temp.second;
                    if(valid(n,newR,newC) && !visited[newR][newC])
                    {
                        arr[newR][newC]=counter;
                        visited[newR][newC]=1;
                        counter++;
                    }
                    else
                    {
                        newR-=temp.first;
                        newC-=temp.second;
                        changeDir=true;
                        break;
                    }
                }
            }
            for(i=1;i<=n;i++)
            {
                for(j=1;j<=n;j++)
                {
                    if(arr[i][j]<10)
                        cout<<0;
                    cout<<arr[i][j]<<" ";
                }
                cout<<endl;
            }
            return 0;
        }
    

    Here is the output where N=5:

    01 02 03 04 05 
    16 17 18 19 06 
    15 24 25 20 07 
    14 23 22 21 08 
    13 12 11 10 09
    

    Thank you.

    0 讨论(0)
  • 2021-01-01 03:43

    I found a way. Now I've to improve it a bit, especially I've to find a cleaner way to build "fdisp". n = 5

    dim = n
    pos = (0, -1)
    fdisp = []
    squares = n % 2 == 0 and n / 2 or n / 2 + 1
    
    for _ in range(squares):
        pos = (pos[0], pos[1] + 1)
        fdisp.append(pos)
    
        fdisp += [(pos[0],pos[1]+i) for i in range(1, dim)]
        pos = fdisp[-1]
        fdisp += [(pos[0]+i,pos[1]) for i in range(1, dim)]
        pos = fdisp[-1]
        fdisp += [(pos[0],pos[1]-i) for i in range(1, dim)]
        pos = fdisp[-1]
        fdisp += [(pos[0]-i,pos[1]) for i in range(1, dim - 1)]
        pos = fdisp[-1]
        dim = dim - 2
    
    matrix = [[0] * n for i in range(n)]
    
    for val,i in enumerate(fdisp):
        matrix[i[0]][i[1]] = val + 1
    
    def show_matrix(matrix, n):
        for i,l in enumerate(matrix):
            for j in range(n):
                print "%d\t" % matrix[i][j],
            print
    
    show_matrix(matrix, n)
    
    0 讨论(0)
提交回复
热议问题