Reverse Spiral Array

x축과 y축의 길이를 입력받아 시계방향으로 회전하며 값이 증가하는 매트릭스를 출력하라. 중앙의 출발지점은 x, y 입력에 따라 달라질 수 있지만 종료지점은 항상 (1,y)가 되어야 한다. (중앙 출발지점 값은 0)

  • 입출력 예
# 입력
5 6
# 출력
 16 17 18 19 20
 15  4  5  6 21
 14  3  0  7 22
 13  2  1  8 23
 12 11 10  9 24
 29 28 27 26 25

# 입력
9 6
# 출력
 32 33 34 35 36 37 38 39 40
 31 12 13 14 15 16 17 18 41
 30 11  0  1  2  3  4 19 42
 29 10  9  8  7  6  5 20 43
 28 27 26 25 24 23 22 21 44
 53 52 51 50 49 48 47 46 45
transpose
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

8개의 풀이가 있습니다.

Ruby

(1,y)에서 출발. 시계반대 방향으로 안으로 회전하는 spiral array를 만든 뒤 역으로 뒤집는다. x,y의 현재위치를 기준으로 다음위치를 산술적으로 계산해서 spiral array를 만들거나, 매트릭스를 90도씩 시계방향으로 회전시키며(reverse.transpose) 마지막 row를 잘라내 spiral array를 만든다.

cube = ->x,y { (1..y).map {|row| [*1..x].product [row]} }
peel = ->cub { cub[0]? cub.pop + peel[cub.reverse.transpose] : [] }
rev_sp = proc { x,y = gets.split.map(&:to_i); r_sp = peel[cube[x,y]].reverse
                puts cube[x,y].map {|r| r.map {|e| "%3d" % r_sp.index(e)}*''} }

Output

#=> rev_sp.()
5 6
 16 17 18 19 20
 15  4  5  6 21
 14  3  0  7 22
 13  2  1  8 23
 12 11 10  9 24
 29 28 27 26 25

#=> rev_sp.()
9 6
 32 33 34 35 36 37 38 39 40
 31 12 13 14 15 16 17 18 41
 30 11  0  1  2  3  4 19 42
 29 10  9  8  7  6  5 20 43
 28 27 26 25 24 23 22 21 44
 53 52 51 50 49 48 47 46 45
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

역으로 (1,y) 부터 시작해서 행렬을 90도 회전해가며 0,-1,-2... 순으로 값을 채운다. 마지막에 전체 값에 x*y-1을 더해 결과를 만든다.

def printMatrix(matrix):
    for i in matrix:
        #print('[', end='')
        for j in i:
            print("%4d" % j, end='')
        print()

def rotate(matrix):
    newMatrix = []
    for i in range(len(matrix[0])):
        row = []
        for j in matrix:
            row.insert(0,j[i])
        newMatrix.append(row)
    return newMatrix


nums=input('x,y:').split()

x = int(nums[0])
y = int(nums[1])

# init matrix
matrix = []

for i in range(y):
    row = []
    for j in range(x):
        row.append(1);
    matrix.append(row)


spiralValue = 0
s_y = y
startIndex = 0
rotateCnt = 0
center = 1

while True:
    for j in range(startIndex, x):
        if matrix[y-center][j] == 1:
            matrix[y-center][j] = spiralValue
            spiralValue -= 1
    #printMatrix(matrix)
    matrix = rotate(matrix)

    rotateCnt += 1

    if rotateCnt%2 == 1:
        startIndex += 1

    for j in range(startIndex, s_y):
        if matrix[x-center][j] == 1:
            matrix[x-center][j] = spiralValue
            spiralValue -= 1
        else:
            center += 1
            s_y -= 1
    #printMatrix(matrix)
    matrix = rotate(matrix)

    if spiralValue*(-1) >= x*y:
        #print("spiral:", spiralValue, " end!")
        break

#print('Numbering finished. Rotating...')
while matrix[-1][0] != 0:
    matrix = rotate(matrix)

for row in matrix:
    for j in range(x):
        row[j] = row[j] + x*y -1

print('Result:')
printMatrix(matrix)
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.


#include <stdio.h>
#include <stdlib.h>

void main(void) {
    int x, y;
    int row, col;
    int value;
    int outx, outy;
    printf("#입력 : ");
    scanf("%d", &x);
    scanf("%d", &y);


    outx = x;
    outy = y;


    //printf("%d,%d \n",x, y);

    col = x -1;
    row = y -1;
    value = (x*y)-1;

    int **arr;
    arr = (int**)malloc(sizeof(int)*x);
    for(int i = 0; i < y; i++) {
        arr[i] = (int*)malloc(sizeof(int)*y);
    }
    for(int i = 0 ; i < x; i++) {
        for(int j = 0 ;  j <  y; j++) {
            arr[i][j] = 0;
        }
    }


    int sx = 0, sy = 0;
    int ex = x, ey = y;
    while(value > 0) {

        for(int i = sx ; i < ex; i++){
            arr[i][row] = value;
            if(value > 0)
                value --;
            col = i;
        }
        row--;
        x--;
        for(int j = row ; j>=sy; j--){
            arr[col][j] = value;
            if(value > 0)
                value --;

            row = j;
        }
        col--;
        for(int i = col ; i>=sx ; i--) {
            arr[i][row] = value;
            if(value > 0)
                value --;

            col = i;
        }
        row++;
        for(int j = row ; j < ey-1 ; j++) { 
            arr[col][j] = value;
            if(value > 0)
                value --;

            row = j;
        }

        sx++;
        sy++;
        ex--;
        ey--;

   }
   printf("\n\n #출력 : \n\n");
   for(int j = 0 ;  j <  outy; j++) {
        for(int i = 0 ; i < outx; i++){
            printf("%d\t", arr[i][j]);
        }
        printf("\n");
    }
}

```

※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

C언어

#include <stdio.h>
enum { left, right, top, bottom };
int main()
{
    int x_size = 9, y_size = 6, max = (x_size * y_size - 1);
    int a[y_size][x_size];
    for(int i = 0; i < y_size; i++){
        for(int j = 0; j < x_size; j++){
            a[i][j] = 0;
        }
    }
    int d = right, x = 0, y = y_size - 1;
    for(int v = max; v >= 0; v--){
        a[y][x] = v;
        switch(d){
            case left:
                if(x == 0 || a[y][x-1] > 0){ d = bottom; y++; } else { x--; }
                break;
            case right:
                if(x == x_size - 1 || a[y][x+1] > 0){ d = top; y--; } else { x++; }
                break;
            case top:
                if(y == 0 || a[y-1][x] > 0){ d = left; x--; } else { y--; }
                break;
            case bottom:
                if(y == y_size -1 || a[y+1][x] > 0) { d = right; x++; } else { y++; }
                break;
        }
    }
    for(int i = 0; i < y_size; i++){
        for(int j = 0; j < x_size; j++){
            printf("%d\t", a[i][j]);
        }
        printf("\n");
    }
    return 0;
}
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.
class cursor(list):
    def __init__(self, y, x, board):
        super().__init__(self)
        self.y, self.x, self.board = y, x, board
        self.l = len(board[0]), len(board)
    def rot(self):
        self[0:2] = (self[1], -self[0])
    def auto_turn(self):
        if all((0 <= self.x + self[0] < self.l[0],
               0 <= self.y + self[1] < self.l[1])):
               if self.board[self.y+self[1]][self.x+self[0]] == 0:
                   return
        self.rot()
    def move(self, n):
        self.board[self.y][self.x] = n
        self.auto_turn()
        self.x, self.y = self.x+self[0], self.y+self[1]
    def getboard(self):
        return self.board

while __name__ == '__main__':
    x, y = list(map(int, input().split()))
    c = cursor(y-1, 0, list(list(0 for j in range(x)) for i in range(y)))
    c.extend([1,0])
    for x in range(x*y-1, 0-1, -1):
        c.move(x)
    for i in c.getboard():
        print(' '.join('%-4d'%j for j in i))

리스트 상속하여 cursor 클래스 만듦.

파이썬 3.5.1

※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

JAVA

높이 : h, 너비 : w 라 할 때, 시작을 h*h - 1 ~ 0 까지 채우는 것. 시작 점은 array[0][h-1] 일 것. 오른쪽 -> 위쪽 -> 왼쪽 -> 아래쪽 -> 오른쪽 순으로 방향을 순환, 방향을 변경하는 조건은 다음 채울 위치가 제시된 너비, 높이에 닿을 경우, 혹은 이미 값이 채워져 있는 경우.


public class ReverseSpiralArray {

    public static final int SIZE = 100;
    static int w;
    static int h;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        w = Integer.valueOf(args[0]);
        h = Integer.valueOf(args[1]);
        int[][] A = spiral(w, h);
        for (int i=0; i<h; i++) {
            for (int j=0; j <w ; j++) {
                System.out.format("%3d ", A[i][j]);
            }
            System.out.println();
        }
    }


    public static int[][] spiral(final int w, final int h) {

        int[][] array = new int[SIZE][SIZE];
        int direction = 0;
        int number = w*h -1;
        Point current = new Point(h-1, 0);
        Point next;
        while(number >= 0) {
            array[current.getY()][current.getX()] = number--;
            next = nextPoint(current, direction);
            if (isCorrectPosition(array, next)) {
                current = next;
            } else {
                direction++;
                current = nextPoint(current, direction);
            }   
        }
        return array;
    }

    private static Point nextPoint(Point current, int direction) {
        final int DIRECTION_RIGHT = 0;
        final int DIRECTION_UP = 1;
        final int DIRECTION_LEFT = 2;
        final int DIRECTION_DOWN = 3;
        Point next = null;

        switch(direction%4) {
        case DIRECTION_RIGHT :
            next = new Point(current.getY(), current.getX()+1);
            break;
        case DIRECTION_UP :
            next = new Point(current.getY()-1, current.getX());
            break;
        case DIRECTION_LEFT :
            next = new Point(current.getY(), current.getX()-1);
            break;
        case DIRECTION_DOWN :
            next = new Point(current.getY()+1, current.getX());
            break;
        }
        return next;
    }

    private static boolean isCorrectPosition(int[][] array, Point next) {
        int x = next.getX();
        int y = next.getY();
        if (x < 0 || y < 0 || x >= w || y >= h) {
            return false;
        }
        if (array[y][x] != 0) {
            return false;
        }
        return true;
    }

    private static class Point {
        private int x;
        private int y;

        public Point(int y, int x) {
            this.x = x;
            this.y = y;
        }
        public void setX(int x) {
            this.x = x;
        }
        public void setY(int y) {
            this.y = y;
        }
        public int getX() {
            return x;
        }
        public int getY() {
            return y;
        }
    }
}

※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

2차원리스트를 이용하며, 변수명만 정직하게 넣어주면 헷갈리지 않습니다.

# python3.5
def do(w, h):
    grid = [list([-1] * w) for _ in range(h)]
    directions = ((1, 0), (0, -1), (-1, 0), (0, 1))
    d = 0
    curpos = (h-1, 0)

    def getNext():
        nonlocal curpos, d
        row, col = curpos
        ox, oy = directions[d]
        if (0 <= col + ox < w) and (0 <= row + oy < h) and grid[row+oy][col+ox] < 0:
            pass
        else:
            d = (d + 1) % 4
            ox, oy = directions[d]
        curpos = (row+oy, col+ox)

    for i in range(w*h)[::-1]:
        row, col = curpos
        grid[row][col] = i
        getNext()

    for row in grid:
        print(" ".join("{:3d}".format(x) for x in row))

if __name__ == '__main__':
    do(9, 6)
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

종료지점부터 시작해서 출발지점까지 반대로 가도록 해 봤습니다. 중간에 int j가 있는데 go_%%의 출발 지점과 끝 지점을 맞추기위해 넣었습니다.

```{.java}

import java.util.Scanner;

public class reverse_spiral {

public static void main(String[] args) {
    int x, y = 0;
    Scanner scan = new Scanner(System.in);
    x = scan.nextInt();
    y = scan.nextInt();

    int[][] arr = sql_arr(x, y);
    for(int j = 0; j < y; j++){
        for(int i = 0; i < x; i++)
            System.out.print(arr[i][j] + " ");
        System.out.println();
    }
}
static int [][] sql_arr(int x, int y){
    int[][] arr = new int [x][y];
    int xy;
    if(x < y)
        xy = 2 * x;
    else
        xy = 2 * y - 1;
    for(int i = 0; i < xy; i++){
        switch(i % 4){
        case 0 :
            arr = go_right(arr, x, y--, i/4);
            break;
        case 1 :
            arr = go_up(arr, x--, y, i/4);
            break;
        case 2 : 
            arr = go_left(arr, x, y--, i/4);
            break;
        case 3 :
            arr = go_down(arr, x--, y, i/4);
            break;
        }
    }
    return arr;

}
static int[][] go_right(int[][]arr, int x, int y, int j){
    int num = x * y - 1;
    for(int i = j; i < x+j; i++)
        arr[i][arr[0].length-j-1] = num--;
    return arr;

}
static int[][] go_left(int[][]arr, int x, int y, int j){
    int num = x * y;
    for(int i = x+j; i >= j; i--)
        arr[i][j] = num--;
    return arr;

}
static int[][] go_up(int[][]arr, int x, int y, int j){
    int num = x * y;
    for(int i = y+j; i >= j; i--)
        arr[arr.length-j-1][i] = num--;
    return arr;

}
static int[][] go_down(int[][]arr, int x, int y, int j){
    int num = x * y;
    for(int i = j; i <= y+j; i++)
        arr[j][i] = num--;
    return arr;

}

}

※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

풀이 작성

※ 풀이작성 안내
  • 본문에 코드를 삽입할 경우 에디터 우측 상단의 "코드삽입" 버튼을 이용 해 주세요.
  • 마크다운 문법으로 본문을 작성 해 주세요.
  • 풀이를 읽는 사람들을 위하여 풀이에 대한 설명도 부탁드려요. (아이디어나 사용한 알고리즘 또는 참고한 자료등)
  • 작성한 풀이는 다른 사람(빨간띠 이상)에 의해서 내용이 개선될 수 있습니다.
목록으로
코딩도장

코딩도장은 프로그래밍 문제풀이를 통해서 코딩 실력을 수련(Practice)하는 곳입니다.

transpose x 1

언어별 풀이 현황
전 체 x 8
python x 3
cpp x 1
기 타 x 1
ruby x 1
java x 2