코딩테스트/프로그래머스

[프로그래머스] Lv1.택배 상자 꺼내기.java.

개발김쿙 2025. 5. 16. 16:35

<링크>

https://school.programmers.co.kr/learn/courses/30/lessons/389478

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

<문제 설명>

1~n의 번호가 있는 택배 상자가 창고에 있다.

당신은 택배를 정리 중이다.

왼쪽에서 오른쪽으로 가면서 1번 상자부터 번호 순서대로 한개씩 놓는다.

가로로 택배를 w개 놓았다면 이번에는 오른쪽에서 왼쪽 방향으로 그 위층에 한개씩 쌓는다.

그 층에 다시 w개를 놓았다면 이를 반복한다. 이러한 방식으로 n개 상자를 쌓는다.

w=6, n=22 일 경우

택배 상자 A번을 꺼내려면 그 위의 상자를 모두 꺼내야합니다.

1번을 꺼내려면 12, 13번 상자를 꺼내야합니다.

당신이 꺼내려는 상자 번호가 주어질 때, 꺼내려는 상자를 포함하여

총 몇개의 상자를 꺼내야 하는지 알고 싶다. 이 때,

 

- 창고에 있는 택배 상자의 개수 n, (2<= n <= 100)

- 가로로 놓는 상자의 개수 w, (1<= w <= 10) 

- 택배 상자의 번호를 나타내는 정수 num, (1<= num <= n)

 

<문제 해석>

1. 왼쪽으로만 쌓는 것이 아니고, 왼쪽 오른쪽 번갈아가며 쌓아간다. 

2. 그렇다면 홀수라인은 왼쪽, 짝수라인은 오른쪽으로 쌓아오를 것이다.

3. 마지막 라인의 택배상자 갯수는 n%w 이거나 n%w ==0일 경우 w개,

    해당 라인 레벨은 n/w의 몫 +1 으로 생각했으나, n=6, w=6일 경우 2를 출력한다. 

    0-Based로 level = (num - 1) / w + 1 로 풀자.

4. answer은 꺼내려는 상자를 포함한 꺼내야하는 상자의 총 개수

5. num번째 박스 포함이므로 1 + (마지막 라인 층수 - 현재 라인 층수) 를 계산하고,

  마지막 라인의 박스 수와 방향을 생각해서 -1 해주면 되겠다.

 

이제 풀어보자.

 

<문제 풀이>

class Solution {
    public int solution(int n, int w, int num) {
        // 1. num번 상자가 속한 라인 계산 (1-based)
        int numLine = (num - 1) / w + 1;  // num이 속한 라인의 번호

        // 2. 전체 라인 수 계산
        int totalLines = (n + w - 1) / w;  // 전체 라인 수

        // 3. 마지막 라인 박스 개수 계산
        int lastLineBoxes = n % w == 0 ? w : n % w;

        // 4. num번 상자가 속한 라인과 마지막 라인의 관계만 고려
        // 현재 라인부터 마지막 라인까지 꺼내야 하는 상자 개수 계산
        int answer = 1; // 현재 num 상자 포함
        
        // num번 상자 속한 라인과 마지막 라인의 관계에 따른 계산
        if (numLine == totalLines) { // num이 마지막 라인에 있을 경우.
            return answer;
        } 
        else{ // num이 마지막이 아닌 경우
            int numIndex = (num - 1) % w + 1;
            
            // 1. totalLines -numLine 가 홀수일 경우(서로 방향이 다름)
            if((totalLines - numLine) %2 ==1){
                // 서로 방향이 다르므로 numIndex + lastLineBoxes가 w보다 작거나 같은 경우 
                // 해당 인덱스에서 마지막 라인의 박스 개수가 채워지지 않음.
                if(numIndex + lastLineBoxes <= w){
                    answer += (totalLines - numLine) - 1;
                }
                // 큰 경우
                else{
                    answer += (totalLines - numLine);
                }
            }
            else{
                // 2. totalLines -numLine 가 짝수일 경우(방향 같음)
                // numIndex가 lastLineBoxes보다 작거나 같을 경우
                if(numIndex <= lastLineBoxes){
                    answer += (totalLines - numLine);
                }
                else answer += (totalLines - numLine) -1;
            }
        }

        return answer;
    }
}