728x90

 

 

문제

 

지난 주에 제주도에 다녀온 선생님은 냉장고에 제주 초콜릿을 숨겨두고 몰래 먹고 있다.

눈치가 빠른 학생들은 선생님의 초콜릿을 훔쳐 먹었다! 이를 알아챈 선생님은 포스트잇에 현재 초콜릿의 남은 개수를 적어 놓아 학생들이 먹는 일이 없도록 하려고 한다. 다만, 이 숫자를 학생들이 바꿔버릴 수 있기 때문에 특정한 규칙으로 초콜릿의 개수를 적으려고 한다.

초콜릿의 종류는 총 5개 있으며 각각 한라봉(H), 감귤(T), 백년초(C), 키위(K), 녹차(G)이다.

남은 초콜릿의 개수를 적는 규칙은 다음과 같다.

  1. 첫 번째 줄에 남아있는 초콜릿의 총 개수를 적고, 바로 뒤에 7H (개를 아스키 문자로 형상화한 단어)를 적는다.
    • 초콜릿의 총 개수를 적을 때에는 바로 전 단계에 남아있던 초콜릿의 총 개수의 일의 자리의 값을 진법으로 하여 적는다.
    • 단, 바로 전 단계에 남아있던 초콜릿의 총 개수의 일의 자리의 값이 0 또는 1이라면, 10진법으로 적는다.
  2. 두 번째 줄에 남아있는 개수가 많은 순으로 각 초콜릿의 종류에 대응하는 알파벳을 공백 없이 적는다.
    • 남아있는 개수가 0개인 초콜릿의 종류에 대응하는 알파벳은 적지 않는다.
    • 남아있는 개수가 동일한 초콜릿의 종류가 여러 개일 경우에는 알파벳 순으로 먼저 오는 것이 앞으로 오도록 적는다.
    • 남아있는 초콜릿의 총 개수가 0개일 경우에는 NULL을 적는다.

이제 선생님을 도와서 포스트잇에 적어야 할 초콜릿의 개수를 출력하는 코드를 작성하자!

 

 

제한사항

  • 각 종류별 먹는 초콜릿 수의 합은 처음에 있던 종류별 개수보다 작거나 같음이 보장된다.

 

입출력 예

 

코드

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.StringTokenizer;

public class JUN27535 {
    /* 제주 초콜릿 지키키
    * 이번 단계의 총 갯수를 이전 단계의 총 갯수의 일의 자리 진법으로 바꿔야 함
    * 이전 단계의 일의 자리가 0, 1이면 그냥 씀
    * 끝에 7H 를 붙임
    *
    * 그 후 많이 남은 순으로 정렬
    * 같은 개수면 알파벳 순으로 정렬
    * */

    // H : 한라봉, T : 감귤, C : 백년초, K : 키위, G : 녹차

    static class Choco implements Comparable<Choco> {
        char name;
        int num;

        public Choco(char name, int num) {
            this.name = name;
            this.num = num;
        }

        @Override
        public int compareTo(Choco o1) {
            // 초콜릿 갯수가 같으면 이름 순
            if(this.num == o1.num){
                //이름은 오름차순
                return this.name - o1.name;
            }
            // 초콜릿 개수별 내림차순
            return o1.num - this.num;
        }
    }
    
    static int N; // 먹는 횟수
    static int sum = 0; // 현재 초콜릿 총합
    static StringBuilder sb = new StringBuilder(); // 정답 저장
    static ArrayList<Choco> list = new ArrayList<>(); // 초콜릿 저장
    static ArrayList<Choco> copied = new ArrayList<>(); // 정렬을 위한 리스트
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        
        // 초콜릿 입력
        list.add(new Choco('H', Integer.parseInt(st.nextToken())));
        list.add(new Choco('T', Integer.parseInt(st.nextToken())));
        list.add(new Choco('C', Integer.parseInt(st.nextToken())));
        list.add(new Choco('K', Integer.parseInt(st.nextToken())));
        list.add(new Choco('G', Integer.parseInt(st.nextToken())));
        
        // 현재 초콜릿 총합 구하기, 50일텐데 그냥 구해주자
        for(Choco c : list){
            sum+=c.num;
        }
        
        // 초콜릿 먹을 횟수 입력
        N = Integer.parseInt(br.readLine());
        
        int last = sum%10; //일의 자리 구하기

        // 초콜릿 먹기 시작
        for(int i =0; i < N; i++){
            st = new StringTokenizer(br.readLine());
            sum = 0;

            // 초콜릿 먹으면서 남아있는 초콜릿 갯수 세기
            for(int j = 0; j < 5; j++){
                list.get(j).num-=Integer.parseInt(st.nextToken());
                sum += list.get(j).num;
            }
            
            // 이전 총합의 일의 자리 진법으로 바꾸기
            sb.append(change(last, sum)).append("7H").append("\n");

            // 정렬 하기
            if(sum == 0){
                // 남아있는 초콜릿이 없으면 NULL 출력해야함
                sb.append("NULL").append("\n");
            }else{
                sortChoco();
                for(Choco c : copied){
                    // 남아 있지 않으면 체크할 필요가 없음
                    if(c.num == 0) continue;
                    sb.append(c.name);
                }sb.append("\n");
            }
            // 현재 총합의 일의 자리 저장
            last = sum%10;
        }
        System.out.println(sb);
    }

    // 이전 총합의 일의 자리로 진법 바꾸기
    public static String change(int last, int sum){
        StringBuilder num = new StringBuilder();
        if(last == 0 || last == 1){
            // 전의 총합의 일의 자리가 0, 1이면 10진법으로 하니까 변환 필요 없음
            num.append(sum);
            return num.toString();
        }else{
            if(sum == 0){
                return "0";
            } else{
                // 진법 변환 해주기
                while(sum != 0){
                    num.append(sum%last);
                    sum/=last;
                }
            }
            // 거꾸로 돌려주기 위해 StringBuilder 사용
            return num.reverse().toString();
        }

    }

    // 정렬하기: 초콜릿 많은 순으로 정렬
    public static void sortChoco(){
        // 원본을 정렬하면 뒤에 초콜릿 먹을때 복잡해지니까 복사해서 사용
        copied = (ArrayList<Choco>) list.clone();
        Collections.sort(copied);
    }
}

 

 

풀이

 

진행 순서를 보면

1. 초콜릿 값 넣기

 

2. 초콜릿을 먹음.

 

3. 먹고 남은 초콜릿의 총합을

이전 단계의 초콜릿 총합의 일의 자리 진법으로 변환한 후

'7H'를 붙여서 출력

 

4. 현재 초콜릿의 개수별로 내림차순으로 정렬,

개수가 같을 경우 알파벳 순으로 정렬

 


1. 초콜릿 저장하기

 

저는 우선 초콜릿의 이름과 개수를 저장할 클래스를 만들었습니다.

 

static class Choco implements Comparable<Choco> {
        char name;
        int num;

        public Choco(char name, int num) {
            this.name = name;
            this.num = num;
        }
    }

 

그 후 ArrayList를 만들어서 초코릿을 이름과 개수를 저장했습니다.

 

 

 


2. 초콜릿 먹기

아까 초콜릿을 저장한 list 에서

초콜릿 개수가 저장된 변수에 먹은 만큼 빼주고

합계를 구했습니다.

 


3. 현재 남아 있는 초콜릿을 전 단계의 총합의 일의 자리 진법으로 변환하기

 

이건 글 보다는 그림으로 보시면 편하실 것 같아서 열심히 그려왔습니다.

 

 

 


4. 초콜릿 개수로 정렬하기

 

현재 남아있는 초콜릿 개수가 많은 순으로 정렬을 하면 됩니다.

다만 초콜릿 개수가 같을 때는

알파벳 순으로 정렬을 해주면 됩니다.

 

평소에 자주 사용하는 정렬은 

그냥 비교 대상이 하나였는데

이번에는 비교 조건이 2개가 되어버렸네요 ㅠㅠ

 

게다가 비교하는게 List.....

어떻게 해야할까요?

 

이럴때 자주 사용하는게 바로

CompareTo<T>

static class Choco implements Comparable<Choco> {
        char name;
        int num;

        public Choco(char name, int num) {
            this.name = name;
            this.num = num;
        }
		
        // 이 부분입니다!!!!!
        @Override
        public int compareTo(Choco o1) {
            // 초콜릿 갯수가 같으면 이름 순
            if(this.num == o1.num){
                //이름은 오름차순
                return this.name - o1.name;
            }
            // 초콜릿 개수별 내림차순
            return o1.num - this.num;
        }
    }
    
    static ArrayList<Choco> list = new ArrayList<>();
    
    public static void main(String[] args){
    	Collections.sort(copied); // 이렇게 사용하시면 됩니다.
    }

 

현재 이 문제에서 사용한  CompareTo<T> 입니다.

 

그런데 

문제가 바껴버려서

남아 있는 초콜릿 기준으로 오름차순,

초콜릿 개수가 같다면 알파벳 기준 내림차순으로 하라고 한다면 어떻게 해야할까요?

 

@Override
        public int compareTo(Choco o1) {
            // 초콜릿 갯수가 같으면 이름 순
            if(this.num == o1.num){
                //이름은 내림차순
                eturn o1.name - this.name;
            }
            // 초콜릿 개수별 오름차순
            return this.num - o1.num;
        }

 

여러분도 다 아시겠지만

이렇게 순서를 바꿔주시면 됩니다 ㅎㅎ

 


 

 

이렇게 차근차근 

하나씩 해결을 하다보니 문제가 풀렸네요.

 

CompareTo<T> 의 경우 나중에 제대로 다뤄보도록 하겠습니다.

 

봐주셔서 감사합니다!!

 

다음에 또 봐요

 

'백준 > 실버' 카테고리의 다른 글

백준 > 9711번 > 피보나치 - JAVA  (2) 2023.06.02
백준 > 8911번 > 거북이 - JAVA  (0) 2023.04.01
백준 > 1992번 > 쿼드트리 - JAVA  (0) 2023.02.22

+ Recent posts