‡ CODING TEST STUDY ‡/º 백준

[백준 | Java Bronze II ] (#1673) 치킨 쿠폰

Trudy | 송연 2024. 7. 14. 22:45

문제

https://www.acmicpc.net/problem/1673


접근

강민이는 치킨 한 마리를 주문할 수 있는 치킨 쿠폰을 n장 가지고 있다. 이 치킨집에서는 치킨을 한 마리 주문할 때마다 도장을 하나씩 찍어 주는데, 도장을 k개 모으면 치킨 쿠폰 한 장으로 교환할 수 있다.
강민이가 지금 갖고 있는 치킨 쿠폰으로 치킨을 최대 몇 마리나 먹을 수 있는지 구하여라. 단, 치킨을 주문하기 위해서는 반드시 치킨 쿠폰을 갖고 있어야 한다.

 

예제 입력

4 3
10 3
100 5

 

예제 출력

5
14
124

 

 

  • 쿠폰 4장을 가지고 있고, 도장 3개에 쿠폰 1장을 주는 경우

쿠폰 3장을 통해 3마리를 시키고, 쿠폰 한 장을 더 받는다. 

나머지 쿠폰 두 장을 통해 두 마리를 더 시킨다. 

 

=> 총 5마리

 

  • 쿠폰 10장을 가지고 있고, 도장 3개에 쿠폰 1장을 주는 경우

쿠폰 3장으로 3마리를 시키고, 쿠폰 한 장을 받는다. 

쿠폰 3장으로 3마리를 시키고, 쿠폰 한 장을 받는다. 

쿠폰 3장으로 3마리를 시키고, 쿠폰 한 장을 받는다.

(현재 쿠폰 4장)

쿠폰 3장으로 3마리를 시키고, 쿠폰 한장을 받는다. 

(현재 쿠폰 2장)

나머지 쿠폰 두 장을  통해 두 마리를 더 시킨다. 

 

=> 총 14마리

 

첫번째 제출 - 실패 (런타임 에러: Null Pointer)

package week11.baek.july16.baek;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class B1673 {
    public static void chicken(int n , int k){
        int chicken = 0;
        //쿠폰이 k장 이상일 동안 반복
        while(n >= k) {
            chicken += k;
            n -= k - 1;
        }
        chicken += n;
        System.out.println(chicken);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br  = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        while(st.hasMoreElements()) {
            if(st.countTokens() == 0)  break;

            int n = Integer.parseInt(st.nextToken());
            int k = Integer.parseInt(st.nextToken());

            chicken(n, k);

            st = new StringTokenizer(br.readLine());
        }
    }
}

 

st.hasMoreElements()로 while문의 조건을 걸어주면 안됐다. 

String input;
while((input = br.readLine()) != null && !input.isEmpty()) {
            st = new StringTokenizer(input);

            int n = Integer.parseInt(st.nextToken());
            int k = Integer.parseInt(st.nextToken());

            chicken(n, k);
        }

 

이런 식으로 input에 먼저 br.readLine()으로 받고, 그게 null이지 않을때만 실행되도록 한다. 

input.isEmpty()는 입력된 게 빈 줄 일 경우가 아닐 때 실행되도록 한다. 

 

백준으로 검사를 돌렸을 때는 아래 조건만 걸어줘도 통과됐다. 

while((input = br.readLine()) != null) {

}

 

하지만 인텔리제이에서 입력을 복사해 실행할 때는 뒷 조건까지 붙여줘야 다음 에러가 뜨지 않았다. 

 

 

인텔리제이에서 실행할 때 while((input = br.readLine()) != null) 조건만 사용할 경우 발생하는 NoSuchElementException은 빈 줄이 입력된 경우 발생한다. 백준에서는 입력이 항상 존재하는 상황에서 실행되기 때문에 문제가 발생하지 않지만, 인텔리제이에서는 사용자가 직접 입력을 제공해야 하므로 빈 줄이 입력되는 상황이 발생할 수 있다. 

 

다음은 이러한 문제를 방지하기 위해 while((input = br.readLine()) != null && !input.isEmpty()) 조건을 사용하는 이유이다.

  • 빈 줄 입력 처리: 인텔리제이에서 실행할 때 사용자가 빈 줄을 입력하면 StringTokenizer가 더 이상 토큰을 찾지 못하게 되어 NoSuchElementException이 발생한다.
  • nextToken() 호출 문제: 빈 줄이 입력된 상태에서 nextToken()을 호출하면 토큰이 없기 때문에 예외가 발생한다. 

최종 코드 

package week11.baek.july16.baek;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class B1673 {
    public static void chicken(int n , int k){
        int chicken = 0;
        //쿠폰이 k장 이상일 동안 반복
        while(n >= k) {
            chicken += k;
            n -= k - 1;
        }
        chicken += n;
        System.out.println(chicken);
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br  = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;

        String input;
        while((input = br.readLine()) != null && !input.isEmpty()) {
            st = new StringTokenizer(input);

            int n = Integer.parseInt(st.nextToken());
            int k = Integer.parseInt(st.nextToken());

            chicken(n, k);
        }
    }
}