백준 1913 달팽이 - 자바

손찬호·2024년 4월 26일
0

알고리즘

목록 보기
29/91

홀수인 자연수 N이 주어지면, 다음과 같이 1부터 N2까지의 자연수를 달팽이 모양으로 N×N의 표에 채울 수 있다.

N이 주어졌을 때, 이러한 표를 출력하는 프로그램을 작성하시오. 또한 N2 이하의 자연수가 하나 주어졌을 때, 그 좌표도 함께 출력하시오. 예를 들어 N=5인 경우 6의 좌표는 (4,3)이다.

입력

첫째 줄에 홀수인 자연수 N(3 ≤ N ≤ 999)이 주어진다. 둘째 줄에는 위치를 찾고자 하는 N2 이하의 자연수가 하나 주어진다.

출력

N개의 줄에 걸쳐 표를 출력한다. 각 줄에 N개의 자연수를 한 칸씩 띄어서 출력하면 되며, 자릿수를 맞출 필요가 없다. N+1번째 줄에는 입력받은 자연수의 좌표를 나타내는 두 정수를 한 칸 띄어서 출력한다.

풀이 아이디어

이차원 배열 snail[n][n]을 0으로 초기화하고
int num = N2N^2두고 (0,0)부터 아래로 전진하며 num을 -1씩 빼주며 채운다.
인덱스 범위를 벗어나거나, 아직 기입되지 않은 곳이면
가는 방향 기준으로 왼쪽으로 90도씩 꺾으며 수를 채운다.
이후 (n/2,n/2)에 도달하면 기입하고 반복을 종료한다.

트러블슈팅 - 반복문 종료조건 인덱스

달팽이 배열을 그리는 while문 속에 종료 조건을 처음에는 "if(num == 0)"으로 줬었다.
그렇게 했더니 입출력이 잘못 나왔었다.

입력:
7
35
출력:
49 26 27 28 29 30 31
48 25 10 11 12 13 32
47 24 9 2 3 14 33
46 23 8 1 0 15 34
45 22 7 6 5 16 35
44 21 20 19 18 17 36
43 42 41 40 39 38 37
5 7

논리상 맞다고 생각했는데 실제로 실행해보니 한번 더 돌아서 4를 지워버렸다.
어디를 수정해야하지 싶어서 디버그로 일일히 돌아봤다.
49~1까지 돌려보니까 종료조건을 잘못 설정했다는 것을 깨닫고
"if(num == 1)"로 수정하니까 잘 실행되었다.
생각보다 쉬운 오류였는데 찾느라 시간을 많이 썼다.
앞으로 논리 오류 고칠 때 조건문, 종료조건 위주로 잘 살펴봐야겠다는 생각이 들었다.

while(true){
    next_x = x + dx;
    next_y = y + dy;

    // 배열 범위를 벗어나거나 이미 숫자가 채워진 경우 방향 전환
    if(next_x < 0 || next_x >= n || next_y < 0 || next_y >= n || snail[next_x][next_y] != 0){
        directIndex = (directIndex+1)%4;
        dx = direction[directIndex][0];
        dy = direction[directIndex][1];

        next_x = x + dx;
        next_y = y + dy;
    }
    
    snail[next_x][next_y] = --num;

    // 배열이 모두 채워지면 종료
    if(num == 1){
        break;
    }
    x += dx;
    y += dy;
}

풀이 코드

import java.util.*;

public class _1913 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int target = sc.nextInt();
        sc.close();
        
        // 좌표 y,x

        // 달팽이 배열 채우기
        // 갈 수 있다의 기준은 배열의 범위를 넘어가지 않는 것+0이 아닌 값이 있는지 확인
        // 벽에 부딪히면 왼쪽 90도 방향 전환
        int[][] snail = new int[n][n];
        int num = n*n;
        int x=0, y=0;
        int dx = 1, dy = 0;
        int next_x, next_y;

        snail[0][0] = num;

        // 아래 (1,0) 오른쪽 (0,1) 위 (-1,0) 왼쪽 (0,-1)
        int[][] direction = {{1,0},{0,1},{-1,0},{0,-1}};
        int directIndex = 0;

        while(true){
            
            next_x = x + dx;
            next_y = y + dy;

            // 배열 범위를 벗어나거나 이미 숫자가 채워진 경우 방향 전환
            if(next_x < 0 || next_x >= n || next_y < 0 || next_y >= n || snail[next_x][next_y] != 0){
                directIndex = (directIndex+1)%4;
                dx = direction[directIndex][0];
                dy = direction[directIndex][1];

                next_x = x + dx;
                next_y = y + dy;
            }
            
            snail[next_x][next_y] = --num;
            if(next_x == n/2 && next_y == n/2) {
                break;
            }
            x += dx;
            y += dy;
        }
    
        // 달팽이 배열 출력
        StringBuilder sb = new StringBuilder();
        int target_x = 0, target_y = 0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                // 타겟의 좌표 찾기
                if(snail[i][j] == target){
                    target_x = i+1;
                    target_y = j+1;
                }
                sb.append(snail[i][j]+" ");
            }
            sb.append("\n");
        }
        System.out.print(sb.toString());
        
        // 타겟의 좌표 출력
        System.out.println(target_x+" "+target_y);
    }
}
profile
매일 1%씩 성장하려는 주니어 개발자입니다.

0개의 댓글

관련 채용 정보