문제
https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PobmqAPoDFAUq
N*N의 숫자가 시계 방향으로 중앙을 향해 돌아가는 배열을 만드는 문제입니다.
예를 들어 N=3, N=4일 때의 결과 값은 아래와 같습니다
풀이
우선 달팽이 배열을 확인해보면 일정한 반복을 통해 배열이 이루어지는 것을 볼 수 있습니다.
예를 들어 N=4일 때의 배열을 쪼개보면 아래 그림과 같은 패턴이 나타납니다.
향하는 방향은 오른쪽 -> 아래 -> 왼쪽 -> 위의 반복을 돌며 각각의 크기는 4-> 3 -> 3 -> 2 -> 2 -> 1 -> 1 순으로 변하는 것을 볼 수 있습니다.
추가로 N=5일 때의 패턴을 살펴보겠습니다.
마찬가지로 향하는 방향이 오른쪽 -> 아래 -> 왼쪽 -> 위의 반복을 돌며 각각의 크기는 5 -> 4-> 4-> 3 -> 3 -> 2 -> 2 -> 1 -> 1로 변하는 것을 볼 수 있습니다.
위의 패턴을 파악했다면, 추가로 다음의 두 가지를 고려해야 합니다.
- 방향과 크기가 정해진 배열의 시작점이 어디인지?
- 언제 배열을 끝마쳐야 할 것인지?
첫 번째로, 시작점도 아래 사진 처럼 패턴을 확인할 수 있습니다.
오른쪽을 향하는 방향(->)에서의 시작점은 인덱스가 (0,0) -> (1,1)로 r,c가 각각 1씩 증가하는 것을 볼 수 있고,
아래를 향하는 방향에서의 시작점은 인덱스가 (4,1) -> (3,2)로 r은 증가 c는 감소하는 것을 알 수 있습니다.
이렇게 각 방향의 시작점의 패턴을 파악한 것을 코드로 구현해보았습니다.
첫 1행의 값은 따로 빼두었고, 각 진행 범위의 감소는 K , 시작점의 인덱스 변화는 m을 이용해 구현하였습니다. 그리고 진행범위 K가 0이 된다면 반복을 종료하여 배열 완성을 끝마쳤습니다.
소스코드
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int i = 0; i < T; i++) {
int R = sc.nextInt();
int[][] arr = new int[R][R];
int cnt = 1;
for (int j = 0; j < R; j++) { // 오
arr[0][j] = cnt++;
}
for (int K = R - 1, m = 0; K > 0; K--, m++) {
for (int j = 1; j < K + 1; j++) { // 아래
arr[j + m][R - 1 - m] = cnt++;
}
for (int j = 1; j < K; j++) { // 왼
arr[R - 1 - m][R - 1 - j - m] = cnt++;
}
K = K - 1;
for (int j = 0; j < K; j++) { // 위
arr[R - 1 - j - m][0 + m] = cnt++;
}
for (int j = 0; j < K + 1; j++) { // 오
arr[1 + m][j + m] = cnt++;
}
}
System.out.println("#" + (i + 1));
for (int r = 0; r < R; r++) {
for (int c = 0; c < R; c++) {
System.out.print(arr[r][c] + " ");
}
System.out.println();
}
}
}
}