{ }codelper
목록 채워 만들기값 바꾸기2차원 목록P0128

달팽이 판 채우기

r줄 c칸짜리 판에 1부터 r × c까지의 수를 달팽이 모양으로 채운다. 첫 줄에 r과 c가 주어진다. 맨 왼쪽 위 칸에 1을 쓰고, 오른쪽으로 가며 다음 수를 차례로 쓴다. 다음 칸이 판 밖이거나 이미 수가 쓰인 칸이면, 시계 방향으로 90도 돌아서(오른쪽 → 아래 → 왼쪽 → 위 → 오른쪽) 그쪽 칸에 쓴다. 판을 다 채우면 한 줄씩 출력하라. 수는 r × c의 자릿수만큼의 너비에 오른쪽으로 맞추고(모자란 자리는 앞을 빈칸으로 채움), 수 사이에는 빈칸 하나를 둔다.

입력
1 ≤ r ≤ 50, 1 ≤ c ≤ 50
출력
r줄, 줄마다 수 c개
예시 1 · stdin
3 4
stdout
 1  2  3  4
10 11 12  5
 9  8  7  6
예시 2 · stdin
4 3
stdout
 1  2  3
10 11  4
 9 12  5
 8  7  6
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

판을 0으로 채워 만드는 방법에 이 문제의 첫 함정이 있어요.
Python [[0] * c] * r는 같은 줄 목록 하나를 r번 넣어서, 한 칸에 쓰면 모든 줄의 그 칸이 바뀌어요.
[[0] * c for _ in range(r)]로 줄마다 새로 만들어요.
JS·TS new Array(r).fill(new Array(c).fill(0))도 같은 배열 하나를 모든 칸에 넣으니 Array.from({ length: r }, () => new Array(c).fill(0))로 써요.
Java new int[r][c], C# new int[r, c], C 전역 배열은 처음부터 0이고, C++ vector(r, vector<int>(c, 0))는 줄마다 복사해요.
크레이콘 새목록(r, 새목록(c, 0))도 칸마다 따로 복사해 넣어요.
방향을 시계 방향으로 돌리는 것은 (dy, dx)를 (dx, -dy)로 바꾸는 것, 곧 두 값 맞바꾸기예요.
Python dy, dx = dx, -dy, JS·TS [dy, dx] = [dx, -dy], C# (dy, dx) = (dx, -dy)는 한 번에 바꾸고, C++는 std::swap(dy, dx); dx = -dx;로 임시 변수 없이 쓸 수 있지만, Java·C·크레이콘은 임시 변수 t = dy; dy = dx; dx = -t;가 필요해요.
임시 변수 없이 dy = dx; dx = -dy;로 쓰면 둘째 줄이 이미 바뀐 dy를 써서 대각선으로 가요.
너비는 r × c의 자릿수예요(예: 100칸이면 3).
Python str(v).rjust(w), JS·TS padStart(w), Java String.format("%" + w + "d", v), C printf("%*d", w, v), C++ std::setw(w), C# PadLeft(w), 크레이콘 앞채우기(w)로 맞춰요.

Pythonmain.py · 14 줄
r, c = map(int, input().split())grid = [[0] * c for _ in range(r)]  # 줄마다 새 목록(같은 목록을 r번 넣지 않게)y, x = 0, 0dy, dx = 0, 1  # 오른쪽으로 시작for k in range(1, r * c + 1):    grid[y][x] = k    ny, nx = y + dy, x + dx    if not (0 <= ny < r and 0 <= nx < c and grid[ny][nx] == 0):        dy, dx = dx, -dy  # 시계 방향으로 90도: 두 값을 맞바꾸며 부호 하나를 뒤집는다        ny, nx = y + dy, x + dx    y, x = ny, nxwidth = len(str(r * c))for row in grid:    print(" ".join(str(v).rjust(width) for v in row))
JavaScriptmain.js · 18 줄
const [r, c] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);// 줄마다 새 배열(fill에 배열 하나를 주면 모든 줄이 같은 배열이 된다)const grid = Array.from({ length: r }, () => new Array(c).fill(0));let y = 0, x = 0;let dy = 0, dx = 1; // 오른쪽으로 시작for (let k = 1; k <= r * c; k++) {  grid[y][x] = k;  let ny = y + dy, nx = x + dx;  if (!(ny >= 0 && ny < r && nx >= 0 && nx < c && grid[ny][nx] === 0)) {    [dy, dx] = [dx, -dy]; // 시계 방향으로 90도    ny = y + dy;    nx = x + dx;  }  y = ny;  x = nx;}const width = String(r * c).length;console.log(grid.map((row) => row.map((v) => String(v).padStart(width)).join(" ")).join("\n"));
TypeScriptmain.ts · 19 줄
import { readFileSync } from "node:fs";const [r, c]: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);// 줄마다 새 배열(fill에 배열 하나를 주면 모든 줄이 같은 배열이 된다)const grid: number[][] = Array.from({ length: r }, () => new Array<number>(c).fill(0));let y = 0, x = 0;let dy = 0, dx = 1; // 오른쪽으로 시작for (let k = 1; k <= r * c; k++) {  grid[y][x] = k;  let ny = y + dy, nx = x + dx;  if (!(ny >= 0 && ny < r && nx >= 0 && nx < c && grid[ny][nx] === 0)) {    [dy, dx] = [dx, -dy]; // 시계 방향으로 90도    ny = y + dy;    nx = x + dx;  }  y = ny;  x = nx;}const width: number = String(r * c).length;console.log(grid.map((row) => row.map((v) => String(v).padStart(width)).join(" ")).join("\n"));
JavaMain.java · 35 줄
import java.util.Scanner; public class Main {    public static void main(String[] args) {        Scanner sc = new Scanner(System.in);        int r = sc.nextInt();        int c = sc.nextInt();        int[][] grid = new int[r][c]; // 칸마다 0으로 채워져 있다        int y = 0, x = 0;        int dy = 0, dx = 1; // 오른쪽으로 시작        for (int k = 1; k <= r * c; k++) {            grid[y][x] = k;            int ny = y + dy, nx = x + dx;            if (!(ny >= 0 && ny < r && nx >= 0 && nx < c && grid[ny][nx] == 0)) {                int t = dy; // 시계 방향으로 90도: 임시 변수로 맞바꾼다                dy = dx;                dx = -t;                ny = y + dy;                nx = x + dx;            }            y = ny;            x = nx;        }        String fmt = "%" + String.valueOf(r * c).length() + "d";        StringBuilder out = new StringBuilder();        for (int[] row : grid) {            for (int j = 0; j < c; j++) {                if (j > 0) out.append(' ');                out.append(String.format(fmt, row[j]));            }            out.append('\n');        }        System.out.print(out);    }}
C#Main.cs · 40 줄
using System;using System.Linq;using System.Text; class Program{    static void Main()    {        int[] rc = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();        int r = rc[0], c = rc[1];        int[,] grid = new int[r, c]; // 칸마다 0으로 채워져 있다        int y = 0, x = 0;        int dy = 0, dx = 1; // 오른쪽으로 시작        for (int k = 1; k <= r * c; k++)        {            grid[y, x] = k;            int ny = y + dy, nx = x + dx;            if (!(ny >= 0 && ny < r && nx >= 0 && nx < c && grid[ny, nx] == 0))            {                (dy, dx) = (dx, -dy); // 시계 방향으로 90도: 튜플로 맞바꾼다                ny = y + dy;                nx = x + dx;            }            y = ny;            x = nx;        }        int width = (r * c).ToString().Length;        var sb = new StringBuilder();        for (int i = 0; i < r; i++)        {            for (int j = 0; j < c; j++)            {                if (j > 0) sb.Append(' ');                sb.Append(grid[i, j].ToString().PadLeft(width));            }            sb.Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 33 줄
#include <iomanip>#include <iostream>#include <string>#include <utility>#include <vector> int main() {    int r, c;    std::cin >> r >> c;    std::vector<std::vector<int>> grid(r, std::vector<int>(c, 0)); // 줄마다 따로 복사된다    int y = 0, x = 0;    int dy = 0, dx = 1; // 오른쪽으로 시작    for (int k = 1; k <= r * c; k++) {        grid[y][x] = k;        int ny = y + dy, nx = x + dx;        if (!(ny >= 0 && ny < r && nx >= 0 && nx < c && grid[ny][nx] == 0)) {            std::swap(dy, dx); // 시계 방향으로 90도: 맞바꾸고            dx = -dx;          // 부호 하나를 뒤집는다            ny = y + dy;            nx = x + dx;        }        y = ny;        x = nx;    }    int width = std::to_string(r * c).size();    for (const auto& row : grid) {        for (int j = 0; j < c; j++) {            if (j > 0) std::cout << ' ';            std::cout << std::setw(width) << row[j];        }        std::cout << '\n';    }}
Cmain.c · 29 줄
#include <stdio.h> int grid[50][50]; // 전역 배열은 0으로 채워져 있다 int main(void) {    int r, c;    scanf("%d %d", &r, &c);    int y = 0, x = 0;    int dy = 0, dx = 1; // 오른쪽으로 시작    for (int k = 1; k <= r * c; k++) {        grid[y][x] = k;        int ny = y + dy, nx = x + dx;        if (!(ny >= 0 && ny < r && nx >= 0 && nx < c && grid[ny][nx] == 0)) {            int t = dy; // 시계 방향으로 90도: 임시 변수로 맞바꾼다            dy = dx;            dx = -t;            ny = y + dy;            nx = x + dx;        }        y = ny;        x = nx;    }    int width = snprintf(NULL, 0, "%d", r * c); // r*c의 자릿수    for (int i = 0; i < r; i++) {        for (int j = 0; j < c; j++) printf(j ? " %*d" : "%*d", width, grid[i][j]);        putchar('\n');    }    return 0;}
Craykonmain.cray · 35 줄
rc = 콘솔.수들읽기();r = rc[0];c = rc[1];// 새목록에 목록을 주면 줄마다 따로 복사해 넣는다grid = 새목록(r, 새목록(c, 0));y = 0;x = 0;dy = 0;dx = 1; // 오른쪽으로 시작반복 (k = 1; k <= r * c; k++){    grid[y][x] = k;    ny = y + dy;    nx = x + dx;    만약 (!(ny >= 0 && ny < r && nx >= 0 && nx < c && grid[ny][nx] == 0))    {        t = dy; // 시계 방향으로 90도: 임시 변수로 맞바꾼다        dy = dx;        dx = -t;        ny = y + dy;        nx = x + dx;    }    y = ny;    x = nx;}width = ("" + r * c).길이;각각 (row 에서 grid){    cells = [];    각각 (v 에서 row)    {        cells.넣기(("" + v).앞채우기(width));    }    콘솔.쓰기(cells.잇기(" "));}