[SWEA] D2 - 1954번 | 달팽이 숫자

EllievV·2024년 11월 13일

🐊 CodingTest

목록 보기
9/18

🔍 문제 보러 가기

정수 N을 입력받아 1부터 NN 까지의 숫자가 NN 배열에 시계방향으로 채워진 달팽이 모양을 출력

문제 상세 설명

달팽이는 1부터 N*N까지의 숫자가 시계방향으로 이루어져 있다.

다음과 같이 정수 N을 입력 받아 N크기의 달팽이를 출력하시오.

[예제]

N이 3일 경우,

N이 4일 경우,

[제약사항]

달팽이의 크기 N은 1 이상 10 이하의 정수이다. (1 ≤ N ≤ 10)

[입력]

가장 첫 줄에는 테스트 케이스의 개수 T가 주어지고, 그 아래로 각 테스트 케이스가 주어진다.

각 테스트 케이스에는 N이 주어진다.

[출력]

각 줄은 '#t'로 시작하고, 다음 줄부터 빈칸을 사이에 두고 달팽이 숫자를 출력한다.

(t는 테스트 케이스의 번호를 의미하며 1부터 시작한다.)

입력출력
2
3
4
#1
1 2 3
8 9 4
7 6 5
#2
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7

내 코드

package D2;

//SWEA D2 1954번 "달팽이 숫자" 문제 풀이 

import java.util.*;

public class N1954 {
	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);
		
		int T = scan.nextInt();
		
		StringBuilder result = new StringBuilder();
				
		for(int i = 1; i <= T; i++) {
			int N = scan.nextInt();
			result.append(String.format("#%d\n", i)).append(solution(N));
		}
		System.out.print(result);
		
	}
	
	public static String solution(int N) {
		
		int[][] arr = new int[N][N];
		
		// 반복 횟수 구하기
		int cnt = 0;
		if (N%2 == 0) {
			cnt = N/2;
		} else {
			cnt = N/2 + 1;
		}
		
		int num = 0;
		
		for (int i = 0; i < cnt; i++) { 
			for(int j = i; j < N-i; j++) { // ->
				arr[i][j] = ++num;
			}
			
			for(int j = i+1; j < N-i; j++) { // 위 -> 아
				arr[j][N-1-i] = ++num;
			}
			
			for(int j = N-2-i; j >= i; j--) { // <-
				arr[N-1-i][j] = ++num;
			}
			
			for(int j = N-2-i; j >= i+1; j--) { // 아래 -> 위
				arr[j][i] = ++num;
			}
			
			if (num > N*N) break;
		}
		
		StringBuilder result = new StringBuilder();
		
		// 출력
		for (int i = 0; i < N; i++) {
			for(int j = 0; j < N; j++) {
				result.append(arr[i][j] + " ");
			}
			result.append("\n");
		}
		return result.toString();
	}

}

접근 방법

dx, dy 테크닉 깜박해서 복잡한 반복문으로 구현했다.. 😅

  1. 반복 횟수는 N을 2로 나눈 값으로 정한다. 만약 N이 홀수라면, 반복 횟수는 N/2 + 1로 설정한다.
  2. 각 반복마다 4방향으로 숫자를 채운다.
    왼 → 오, 위 → 아래, 오 → 왼, 아래 → 위

개선 코드

package D2;

//SWEA D2 1954번 "달팽이 숫자" 문제 풀이 개선

import java.util.*;

public class N1954_b {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		int T = scanner.nextInt();
		
		StringBuilder result = new StringBuilder();
		
		for (int i = 1; i <= T; i++) {
			int N = scanner.nextInt();
			
			result.append(String.format("#%d\n", i)).append(solution(N));
			
		}
		
		System.out.print(result);
		scanner.close();
	}
	
	public static String solution(int N) {
		
		int[][] arr = new int[N][N];
		
		// 방향 설정 : 오른쪽(0), 아래(1), 왼쪽(2), 위(3)
		int[] dx = {0, 1, 0, -1};
		int[] dy = {1, 0, -1, 0};
		
		int num = 1;
		int x = 0, y = 0; // 시작 좌표 (0, 0)
		int direction = 0; // 초기 방향 : 오른쪽
		
		
		while (num <= N*N) {
			arr[x][y] = num++;
			
			// 다음칸으로 이동할 좌표 계산
			int nx = x + dx[direction];
			int ny = y + dy[direction];
			
			// 이동할 좌표가 범위를 벗어나거나 이미 숫자가 채워져 있으면 방향을 바꿈
			if (nx < 0 || nx >= N || ny < 0 || ny >= N || arr[nx][ny] != 0) {
				direction = (direction + 1) % 4;
				nx = x + dx[direction];
				ny = y + dy[direction];
			}
			
			// 새로운 위치로 이동 
			x = nx;
			y = ny;
			
		}
		
		
		// 결과 문자열 만들기
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				result.append(arr[i][j]);
				if (j < N - 1) {
					result.append(" ");
				}
			}
			result.append("\n");
		}
		
		return result.toString();
	}
}

Point

  1. dx, dy 배열 사용

    dx는 x 좌표의 변화량을, dy는 y 좌표의 변화량을 나타낸다.

    dx[0] = 0, dy[0] = 1 : 오른쪽 한 칸 이동

    dx[1] = 1, dy[1] = 0 : 아래로 한 칸 이동

    dx[2] = 0, dy[2] = -1 : 왼쪽 한 칸 이동

    dx[3] = -1, dy[3] = -1 : 위로 한 칸 이동

  1. 방향 전환 로직

    각 방향에 대한 dx와 dy를 기반으로, 현재 위치에서 nx, ny를 계산한다.

    만약 계산된 (nx, ny) 좌표가 배열의 범위를 벗어나거나 이미 값이 채워져 있으면, 방향을 전환한다.

    방향은 direction = (direction + 1) % 4 로 순차적으로 변경된다.

  1. 반복문 통합

    기존 코드는 4개의 방향에 대해 각각의 for문을 작성했다면, 개선된 코드는 하나의 while문 안에서 dx, dy 배열을 사용해 위치를 이동시키고 방향을 전환하는 방식으로 처리했다.

0개의 댓글