관리 메뉴

JumpUp

프로그래머스 [방금그곡] 본문

알고리즘

프로그래머스 [방금그곡]

yeunnnn 2021. 4. 16. 21:02

2018 KAKAO BLIND RECURITMENT [3차] 문제

[N진수 게임], [파일명 정렬], [압축]은 어렵지 않게 풀었는데 [방금그곡]문제는 다른 사람의 풀이를 보고서야 모든 테스트케이스를 통과할 수 있었다. 보니까 다른 문제들은 정답률이 대개 90%가 넘는 거에 비해 이 문제는 40%대 였다. 수정 전 풀이과정에서 놓친 부분들을 다시 살펴보면서 수정 한 코드를 다시 리뷰해보겠다.

 

입력 형식

 


 

수정 전

수정 전 결과

 

<풀이과정>

1. 입력 데이터 정제

A# => a, B# => b 처럼 음을 비교하기 쉽게 바꿈. //sheetMusic()를 만들어 이 과정을 수행함.

musicinfos {음악 시작 기각, 음악 끝난 시각, 음악 제목, 악보} => musicinfos {재싱시간, 음악제목, 악보}로 원하는 데이터로 입력 데이터를 바꿈.

2. 재생시간이 악보 길이보다 길면,재싱시간만큼 음악을 반복시킴

짧다면, 재싱시간만큼 악보를 자름.

3. 조건에 부합하는 musicinfo들의 인덱스를 리스트에 추가함.

4. 리스트의 크기가 2 이상이라면, 가장 긴 재생시간을 가진 음악 제목을 반환.

크기가 1이라면, 조건에 부합하는 음악제목을 반환.

그것도 아니라면, "(None)"을 반환.

 

이 과정에서 제대로 구현하지 못한 것들을 빨간색으로 표시하였다.

첫째, A# => a, B# => b 처럼 음을 비교하기 쉽게 바꿈.

1, 2차 시도 시에는 이 과정마저 고려하지 않았다. 그러다 보니 악보에 네오가 기억한 멜로디가 포함되는지 확인하는 과정에서 문제가 발생한다. 

예)

네오가 기억한 멜로디 : ABC

악보 : ABC#

contain()메소드로 확인하면, true로 반환된다. 같은 멜로디가 아님에도 불구하고.

그렇기에 C#이 같은 하나의 음으로 인식될 수 있도록 C# => c로 바꾸는 과정이 필요한 것이다.

 

둘째, 재싱시간만큼 음악을 반복시킴

예) ABc으로 이루어진 악보가 10분간 재생된다 하자.

재생시간만큼 음악을 반복시킨다 하면,

ABcABcABcA 로 악보가 이루어져야 한다.

하지만, 내가 구현한 코드대로 한다면

ABcABcABc 로 악보가 이루어진다.

 

셋째, 가장 긴 재생시간을 가진 음악 제목을 반환.

조건에 부합하는 음악이 여러 개라면, 가장 긴 재생시간을 가진 음악 제목을 반환하고, 가장 긴 재생시간을 가진 음악도 여러개라면 가장 먼저 입력된 음악제목을 반환해야 한다.

하지만, "가장 긴 재생시간을 가진 음악도 여러개라면 가장 먼저 입력된 음악제목을 반환해야 한다."  이 부분을 고려하지 못한 코드로 구현하였다.

 

import java.util.*;

public class 방금그곡 {
    public static String solution(String m, String[] musicinfos) {
    	m = sheetMusic(m);
        int playingTime , hour, min = 0;
        String sound = "";
        List<Integer> select = new ArrayList<>();
        for(int i=0;i<musicinfos.length;i++){
            sound = musicinfos[i].split(",")[3];
            musicinfos[i] = musicinfos[i].replace(sound, sheetMusic(sound));
            sound = musicinfos[i].split(",")[3];

            hour = Integer.parseInt(musicinfos[i].split(",")[1].split(":")[0]) - Integer.parseInt(musicinfos[i].split(",")[0].split(":")[0]);
            min = Integer.parseInt(musicinfos[i].split(",")[1].split(":")[1]) - Integer.parseInt(musicinfos[i].split(",")[0].split(":")[1]);
            playingTime = hour*60 + min;
            musicinfos[i] = musicinfos[i].replace(musicinfos[i].split(",")[0]+","+musicinfos[i].split(",")[1], Integer.toString(playingTime));
           
           if(sound.length() < playingTime){
                  for(int j=0;j<playingTime/sound.length()-1;j++){
                       musicinfos[i] += sound;
                  }
           }else{
              musicinfos[i] = musicinfos[i].replace(sound, sound.substring(0,playingTime));
           }

	   if(musicinfos[i].split(",")[2].contains(m)) {
                 select.add(i);
 	   }
       }
        
       int time, longPlayingTime = 0;
       String answer = "";
       
       if(select.size() > 1){
       	longPlayingTime = Integer.parseInt(musicinfos[select.get(0)].split(",")[0]);
            for(int i=1;i<select.size();i++){
                time = Integer.parseInt(musicinfos[select.get(i)].split(",")[0]);
                if(Integer.parseInt(musicinfos[select.get(i)].split(",")[0]) == Math.max(longPlayingTime,Integer.parseInt(musicinfos[select.get(i)].split(",")[0]))){
                    longPlayingTime = Integer.parseInt(musicinfos[select.get(i)].split(",")[0]);
                    answer = musicinfos[select.get(i)].split(",")[1];
                }else{
                	answer = musicinfos[select.get(0)].split(",")[1];
                }

            }
            }else if(select.size() == 1){
            answer = musicinfos[select.get(0)].split(",")[1];
        }else{
            answer = "(None)";
        }

        return answer;
    }
    
    public static String sheetMusic(String sound){
        for(int i=0;i<sound.length();i++){
            if(sound.charAt(i) == '#') sound = sound.replaceFirst("[A-G]#",sound.substring(i-1,i).toLowerCase());
        }
        return sound;
    }
}

 

 

수정 후

수정 후 결과

reference : hongjuzzang.github.io/solution/code_p17683/

 

[java] 프로그래머스 - 방금그곡

프로그래머스 - 방금그곡 문제풀이

hongjuzzang.github.io

 

다른 분이 풀이한 과정을 보니, 내가 어떤 부분들을 놓쳤는지 알게 되었고 바로 수정을 해보았다.

<수정 전 후 비교 풀이과정>

1. 필요한 요소들을 Info 클래스로 만들었다.

조건에 부합한 가장 긴 음악시간이 여러 개 일 경우, 가장 먼저 입력된 음악 제목을 반환하기 위해 필요한

musicinfo의 인덱스를 저장할 index와 

재생시간, 음악 제목, 재생시간에 맞춰 가공한 악보로 이루어졌다.

 

2. 재생시간보다 악보의 길이가 같거나 길어질 때까지 음악을 반복시킨다(=악보를 이어 붙인다)

그러고 나서, 재생시간만큼 악보를 잘라낸다.

 

3. getMelody(), getPlayingTime(), getTotalMelody()와같이 기능을 분리해 메서드를 생성했다.

그러고 나니 코드 가독성도 solution() 메서드의 의도도 쉽게 파악할 수 있게 되었다.

 

 

/*
*reference : https://hongjuzzang.github.io/solution/code_p17683/
 */

import java.util.*;

public class 방금그곡 {
    public static void main(String[] args) {
        방금그곡 test = new 방금그곡();
        System.out.println(test.solution("CC#BCC#BCC#BCC#B", new String[]{"03:00,03:30,FOO,CC#B", "04:00,04:08,BAR,CC#BCC#BCC#B"}));
    }
    public String solution(String m, String[] musicinfos) {
        m = getMelody(m);
        int playingTime = 0;
        String melody = "";
        List<Info> selected = new ArrayList<>();
        for(int i=0;i<musicinfos.length;i++){
            String[] t = musicinfos[i].split(",");
            Info info  = new Info(i, getPlayingTime(t[0], t[1]), t[2], getMelody(t[3]));

            if (info.totalMelody.length() >= m.length() && info.totalMelody.contains(m))
                selected.add(info);
        }

        String answer = "";
        if(selected.size() > 1){
            selected.sort((o1, o2) -> {
                if(o1.playingTime == o2.playingTime){
                    return o1.index - o2.index;
                }else return o2.playingTime - o1.playingTime;
            });
            answer = selected.get(0).music;
        }else if(selected.size() == 1){
            answer = selected.get(0).music;
        }else{
            answer = "(None)";
        }

        return answer;
    }
    public String getMelody(String melody){
        for(int i=0;i<melody.length();i++){
            if(melody.charAt(i) == '#') melody = melody.replaceFirst("[A-G]#",melody.substring(i-1,i).toLowerCase());
        }
        return melody;
    }
    public int getPlayingTime(String start, String finish){
        int hour = Integer.parseInt(finish.split(":")[0]) - Integer.parseInt(start.split(":")[0]);
        int min = Integer.parseInt(finish.split(":")[1]) - Integer.parseInt(start.split(":")[1]);
        return hour*60 + min;
    }
    
    class Info{
        private int index;
        private int playingTime;
        private String music;
        private String totalMelody;

        public Info(int index, int playingTime, String music, String melody){
            this.index = index;
            this.playingTime = playingTime;
            this.music = music;
            totalMelody = getTotalMelody(melody, playingTime);
        }

        public String getTotalMelody(String melody, int playingTime){
            if (melody.length() > playingTime)
                return melody.substring(0, playingTime);
            StringBuilder sb = new StringBuilder();
            while (sb.length() < playingTime) {
                sb.append(melody);
            }
            return sb.substring(0, playingTime);
        }
    }
}
728x90