Spiral Array

문제는 다음과 같다:

6 6

  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

위처럼 6 6이라는 입력을 주면 6 X 6 매트릭스에 나선형 회전을 한 값을 출력해야 한다.

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

11개의 풀이가 있습니다. 1 / 2 Page

X,Y = map(int,raw_input().split(' '))
lis = [[-1 for i in xrange(Y)] for j in xrange(X)]
x,y = 0,0
dx,dy = 0,1
count = 0
while lis[x][y] == -1:
    lis[x][y] = count
    count+=1
    x,y = x+dx,y+dy
    if x in [-1,X] or y in [-1,Y] or lis[x][y] != -1:
        x,y = x-dx,y-dy
        dx,dy = dy,-dx
        x,y = x+dx,y+dy
for L in lis:
    for val in L:
        print '%3d'%val,
    print
앗 빠르네요 감사합니다. - 양지훈, 2012/01/14 22:36 M D
코드 멋지네요! - 심재용, 2015/05/04 14:07 M D
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

우선탐색을 하게하여 길을 찾게 하였습니다.

    Sub Main()
        '// 입력
        Dim input() As String = Console.ReadLine.Split(" ")

        Dim x As Integer = 0, y As Integer = 0

        Dim width As Integer = CInt(input(0)), height As Integer = CInt(input(1))
        Dim map(width - 1, height - 1) As Integer
        Dim cnt As Integer = 0, isUp As Boolean = False

        Do
            cnt += 1
            If x + 1 < width AndAlso map(x + 1, y) = 0 And Not isUp Then map(x + 1, y) = cnt : x += 1 : isUp = False : Continue Do
            If y + 1 < height AndAlso map(x, y + 1) = 0 Then map(x, y + 1) = cnt : y += 1 : isUp = False : Continue Do
            If x - 1 >= 0 AndAlso map(x - 1, y) = 0 Then map(x - 1, y) = cnt : x -= 1 : isUp = False : Continue Do
            If y - 1 >= 0 AndAlso map(x, y - 1) = 0 AndAlso x + y - 1 > 0 Then : map(x, y - 1) = cnt : y -= 1 : isUp = True : Continue Do : ElseIf cnt < width * height Then : isUp = False : cnt -= 1 : Continue Do : End If

            Exit Do
        Loop

        '// 출력
        For yy As Integer = 0 To width - 1
            For xx As Integer = 0 To height - 1
                Console.Write(map(xx, yy) & vbTab)
            Next
            Console.WriteLine()
        Next

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

음.. 아이디어가 없어서 최대한 이해하기 쉽게 했는데, 저장공간이 필요해서 에러네요.

오늘 처음 온 곳인데, 깔끔하고 좋습니다. 많이 활성화 되었으면 좋겠습니다.

using namespace std;

int main(int argc, char *argv[])
{
    int w = 0;
    int h = 6;

    cout << "width: ";
    cin >> w;
    cout << "height: ";
    cin >> h;

    int **arr = new int *[w];
    for(int i = 0; i < w; i++)
    {
        arr[i] = new int[h];
    }

    for(int round = 0, i = 0; i < w * h; round++)
    {
        // top
        for(int x = round; x < w - round && i < w * h; x++)
        {
            arr[x][round] = i;
            i++;
        }

        // right
        for(int y = round + 1; y < h - round && i < w * h; y++)
        {
            arr[w - round - 1][y] = i;
            i++;
        }

        // bottom
        for(int x = w - round - 2; x >= round && i < w * h; x--)
        {
            arr[x][h - round - 1] = i;
            i++;
        }

        // left
        for(int y = h - round - 2; y > round && i < w * h; y--)
        {
            arr[round][y] = i;
            i++;
        }
    }

    for(int y = 0; y < h; y++)
    {
        for(int x = 0; x < w; x++)
        {
            printf("%3d ", arr[x][y]);
        }

        cout << endl;
    }

    for(int i = 0; i < w; i++)
        delete[] arr[i];
    delete[] arr;

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

Swift로 문제 풀어봤습니다.

let x = 6
let y = 6

var i:Int = 0

// Row는 사실상 Y, Column은 사실상 X의 역할을 합니다.
var minRow:Int = 0, minColumn:Int = 0
var maxRow:Int = x-1, maxColumn:Int = y-1
var indexRow:Int = 0, indexColumn:Int = 0

// 표시될 방향
var direction = "Right"

// Spiral 배열
var spiralArray = Array<Array<Int>>()

// 배열을 초기화 하는 함수
func initSpiralArray() -> Void
{
    for i in 0..x {
        var array = Array<Int>()
        for j in 0..y {
            array.append(0)
        }
        spiralArray.append(array)
    }
}

func nextDirection() -> Void
{
    switch direction {
    // 방향이 오른쪽일 경우 indexColumn이 증가, 끝일 경우 방향을 아래로 변경하고 indexRow를 증가, minRow도 증가시킵니다.
    case "Right":
        if indexColumn == maxColumn {
            direction = "Down"
            indexRow++
            minRow++
        } else {
            indexColumn++
        }
    // 방향이 왼쪽인 경우 indexColumn을 감소, 끝일 경우 방향을 위로 변경하고 indexRow를 감소, maxRow도 감소시킵니다.
    case "Left":
        if indexColumn == minColumn {
            direction = "Up"
            indexRow--
            maxRow--
        } else {
            indexColumn--
        }
    // 방향이 위쪽인 경우 indexRow를 감소, 끝인 경우 방향을 오른쪽으로 변경하고 indexColumn을 증가, minColumn도 증가시킵니다.
    case "Up":
        if indexRow == minRow {
            direction = "Right"
            indexColumn++
            minColumn++
        } else {
            indexRow--
        }
    // 방향이 아래인 경우 indexRow를 증가, 끝인 경우 방향을 왼쪽으로 변경하고 indexColumn을 감소, maxColumn도 감소시킵니다.
    case "Down":
        if indexRow == maxRow {
            direction = "Left"
            indexColumn--
            maxColumn--
        } else {
            indexRow++
        }
    default:
        print()
    }
}

func printArray() -> Void
{
    for j in spiralArray {
        println(j)
    }
}

initSpiralArray()

while i != x * y {

    spiralArray[indexRow][indexColumn] = ++i

    // 다음 방향을 미리 지정합니다.
    nextDirection()
}

printArray()

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

오른쪽, 왼쪽, 아래쪽, 위쪽 구현하는 반복문들을 따로 만들어서 처리했습니다. c언어로 작성했습니다.

int row, col;
int i, j, dir=1;        //dir 1 = 오른쪽, 2 = 아래쪽, 3 = 왼쪽, 4=위쪽
int num = 0;
bool finish = true;
int cnt=1;

scanf("%d%d",&row,&col);

int ** arr= (int**)malloc(sizeof(int) * row);   //┐
for(i = 0; i < row; i++)                        //2차원배열 동적할당
    arr[i]=(int *)malloc(sizeof(int)*col);      //┘

for(i = 0; i < col; i++)                        //초기화
{
    for(j = 0; j < row; j++)
        arr[j][i] = 0;
}

i = 0, j = 0;
while(finish)
{
    if(dir == 1)                //오른쪽
    {
        for(;j < row; j++)
        {
            if(arr[j][i] == 0)
            {
                arr[j][i] = num;
                num++;
            }
            else
            {
                break;
            }
        }
        dir++;
        j--;
        i++;
    }

    if(dir == 2)                //아래쪽
    {
        for(;i < col; i++)
        {
            if(arr[j][i] == 0)
            {
                arr[j][i] = num;
                num++;
            }
            else
            {
                break;
            }
        }
        dir++;
        i--;
        j--;
    }

    if(dir == 3)                //왼쪽
    {
        for(;j >= 0; j--)
        {
            if(arr[j][i] == 0)
            {
                arr[j][i] = num;
                num++;
            }
            else
            {
                break;
            }
        }
        dir++;
        j++;
        i--;
    }

    if(i*j == num)
    {
        finish = true;
    }

    if(dir == 4)                //왼쪽
    {
        for(;i > 0; i--)
        {
            if(arr[j][i] == 0)
            {
                arr[j][i] = num;
                num++;
            }
            else
            {
                break;
            }
        }
        dir=1;
        i++;
        j++;
    }

    if(num==row*col)
    {
        finish = false;
    }
}




for(i = 0; i < col; i++)                    //출력
{
    for(j = 0; j < row; j++)
    {
        printf("%4d",arr[j][i]);
    }
    printf("\n");
}

for(i=0; i<row; i++)                        //동적해제
    free(arr[i]);
free(arr);

system("pause");
return 0;
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

Swift로 작성하였습니다.

enum Direction {
    case Right, Down, Left, Up
}

func nextSpiralF(var spiralMap: Array<Array<Int>>)(var direct: Direction) -> ((x: Int, y: Int), Int) -> ((Direction, (x: Int, y: Int), Array<Array<Int>>)) {
    return {
        spiralMap[$0.y][$0.x] = $1
        switch direct {
        case .Right where $0.x + 1 >= spiralMap[0].count || spiralMap[$0.y][$0.x + 1] != -1 : direct = .Down
        case .Down where $0.y + 1 >= spiralMap.count || spiralMap[$0.y + 1][$0.x] != -1 : direct = .Left
        case .Left where $0.x - 1 < 0 || spiralMap[$0.y][$0.x - 1] != -1 : direct = .Up
        case .Up where $0.y - 1 < 0 || spiralMap[$0.y - 1][$0.x] != -1 : direct = .Right
        default: break
        }
        return (direct, $0, spiralMap)
    }
}

func printSpiralMap(spiralMap: Array<Array<Int>>) {
    spiralMap.forEach {
        $0.forEach { print(String(format: "%3d", $0), separator: "", terminator: " ") }
        print("")
    }
}

func main(x x: Int, y: Int) {
    let nextSpiral = nextSpiralF(Array<Array<Int>>(count: y, repeatedValue: Array(count: x, repeatedValue: -1)))(direct: Direction.Right)
    let result = (0..<x * y).reduce( (direct: Direction.Right, point: (x: -1, y: 0), spiralMap: Array<Array<Int>>()) ) {
        switch $0.0.direct {
        case .Right: return nextSpiral(($0.0.point.x + 1, $0.0.point.y), $0.1)
        case .Down: return nextSpiral(($0.0.point.x, $0.0.point.y + 1), $0.1)
        case .Left: return nextSpiral(($0.0.point.x - 1, $0.0.point.y), $0.1)
        case .Up: return  nextSpiral(($0.0.point.x, $0.0.point.y - 1), $0.1)
        }
    }
    printSpiralMap(result.spiralMap)
}

main(x: 6, y: 10)
/*
    Output
  0   1   2   3   4   5 
 27  28  29  30  31   6 
 26  47  48  49  32   7 
 25  46  59  50  33   8 
 24  45  58  51  34   9 
 23  44  57  52  35  10 
 22  43  56  53  36  11 
 21  42  55  54  37  12 
 20  41  40  39  38  13 
 19  18  17  16  15  14
*/
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.
void makeSpiral(int row, int col) {
    int[][] arr = new int[row][col];

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length; j++) {
                arr[i][j] = -1;
            }
        }

        int num = 0; 
        int rIdx = 0, cIdx = 0; 
        Direction direction = Direction.RIGHT;

        while( num < row * col ) {
            arr[rIdx][cIdx] = num++;

            switch ( direction ) {
            case RIGHT:
                if( cIdx+1<col && arr[rIdx][cIdx+1] == -1 ){
                    cIdx++;
                }else {
                    direction = Direction.BOTTOM;
                    rIdx++;
                }
                break;
            case BOTTOM:
                if( rIdx+1<row && arr[rIdx+1][cIdx] == -1 ){
                    rIdx++;
                }else {
                    direction = Direction.LEFT;
                    cIdx--;
                }
                break;
            case LEFT:
                if( cIdx-1>=0 && arr[rIdx][cIdx-1] == -1 ){
                    cIdx--;
                }else {
                    direction = Direction.TOP;
                    rIdx--;
                }               
                break;
            case TOP:
                if( rIdx-1>=0 && arr[rIdx-1][cIdx] == -1 ){
                    rIdx--;
                }else {
                    direction = Direction.RIGHT;
                    cIdx++;
                }
                break;
            default:
                break;
            }
        }
        for (int i = 0; i < row; i++) {
            System.out.println();
            for (int j = 0; j < col; j++) {
              System.out.print(arr[i][j] + " ");
            }
        }
}
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

허접한 풀이

void main(void) {
    int height = 0;
    int width = 1;

    while(height != width) {
        scanf("%d", &height);
        scanf("%d", &width);
    }

    int** spiral = (int**) malloc (sizeof(int*) * width);
    for(int i = 0 ; i< width; i++)
        spiral[i] = (int*) malloc (sizeof(int) * width);

    for(int i = 0 ; i< width; i++) 
        for(int j = 0 ; j< width; j++)
            spiral[i][j] = 0;

    int value = 0;
    int i = 0;
    int j = 0;
    int s_x = 0;
    int s_y = 0;
    int e_x = width-1;
    int e_y = height-1;
    for(int n = 0 ; n< (width*width); n++) {

        if(j == s_y && i < e_x) {
            spiral[i][j] = value;
            i++;
            if(e_x == i)
                s_y++;
        }
        else if(i == e_x && j < e_y ) {
            spiral[i][j] = value;
            j++;
            if(e_y == j)
                e_x--;
        }
        else if(j == e_y && i >= 0 && i!=s_x) {
            spiral[i][j] = value;
            if(i > 0 )
                i--;
            if(s_x == i)
                e_y--;
        }
        else {
            spiral[i][j] = value;
            j--;
            if(s_y == j)
                s_x++;
        }
        value++;
    }

    for(int i = 0 ; i< width; i++) {
        for(int j = 0 ; j< width; j++) {
            printf("%d\t",spiral[j][i]);
        }
        printf("\n");
    }
}
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

매트릭스 만들어서 채우고 출력.

int main(int argc, const char * argv[]) {
    int r = 6, c = 6;
    int* mat = calloc(r*c, sizeof(int));
    fill(mat, r, c);
    print(mat, r, c);
    free(mat);
    return 0;
}

출력은 간단..

void print(int* mat, int rows, int cols) {
    for (int r = 0; r < rows; r++) {
        for (int c =0; c< cols; c++) {
            printf("%3d", mat[r * cols + c]);
        }
        printf("\n");
    }
}

채우려면... 겹겹이 박스를 그린다.

void fill(int* mat, int rows, int cols) {
    Pen pen = {mat, rows, cols, 0, 0, 0};
    for (int i=0; i < cols-i && i < rows-i; i++) {
        box_(&pen, i, i, rows-i-1, cols-i-1);
    }
}

Pen은 현재 위치와 채울 값을 누적 기록해야 함.

typedef struct Pen {
    int* mat;
    int rows;
    int cols;
    int r;
    int c;
    int value;
} Pen;

박스는 top/left/bottom/right 를 입력으로 받아서 top -> left -> bottom -> right 순서로 줄을 그리자. 박스가 너무 작으면 그리지 말고.

void box_(Pen* pen, int top, int left, int bottom, int right) {
    moveTo(pen, top, left);
    lineTo(pen, top, right); if (top == bottom) return;
    lineTo(pen, bottom, right); if (left == right) return;
    lineTo(pen, bottom, left);
    lineTo(pen, top+1, left);
}

moveTo는.. 위치로 점프하면서 점 찍기

void moveTo(Pen* pen, int r, int c) {
    pen->r = r;
    pen->c = c;
    pen->mat[r * pen->cols + c] = pen->value++;
}

그럼 lineTo 는 현재 위치에서 목표 지점으로 1칸씩 이동 (moveTo이용)

void lineTo(Pen* pen, int r, int c) {
    while (pen->r != r || pen->c != c) {         // 목표 위치에 도달할 때까지
        if (abs(pen->r - r) > abs(pen->c - c)) { // 더 차이 많이 나는 방향으로
            int dr = pen->r < r ? 1 : -1;        // 한칸씩
            moveTo(pen, pen->r + dr, pen->c);    // 이동
        } else {
            int dc = pen->c < c ? 1 : -1;
            moveTo(pen, pen->r, pen->c + dc);
        }
    }
}
※ 상대에게 상처를 주기보다 서로에게 도움이 될 수 있는 댓글을 달아 주세요.

include

include

int main() { int i, j, x, y, N = 0, type = 0; printf("X : "); scanf("%d", &x); printf("Y : "); scanf("%d", &y); int arr; arr = (int)malloc(sizeof(int)y); arr[0] = (int)malloc(sizeof(int)xy); for(i = 1; i < y; i++) { arr[i] = arr[i-1] + x; } for (i = 0; i < y; i++) { for (j = 0; j < x; j++) { arr[i][j] = -1; } } i = 0, j = 0; while (N < xy) { if ((i<0) || (i>=y) || (j<0) || (j>=x) || (arr[i][j] != -1)) { switch (type) { case 0: j--; i++; break; case 1: i--; j--; break; case 2: j++; i--; break; case 3: i++; j++; break; } type = (type+1)%4; } arr[i][j] = N++; switch (type) { case 0: j++; break; case 1: i++; break; case 2: j--; break; case 3: i--; break; } } for (i = 0; i < y; i++) { for (j = 0; j < x; j++) { printf("%3d ", arr[i][j]); } printf("\n"); } free(arr[0]); free(arr); return 0; }

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

풀이 작성

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

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


언어별 풀이 현황
전 체 x 123
java x 25
scala x 3
python x 40
delphi x 1
javascript x 1
lisp x 2
기 타 x 11
go x 1
cpp x 30
objectivec x 1
clojure x 1
ruby x 2
cs x 5