프로그래머스/자바 Lv2

[프로그래머스] Java Lv2. 코딩테스트 연습 > 2018 KAKAO BLIND RECRUITMENT > [3차] 방금그곡 42583

행수쌤 2024. 11. 5. 16:21
728x90
반응형

문제설명

  • 방금그곡 서비스에서는 음악 제목, 재생이 시작되고 끝난 시각, 악보를 제공한다.
  • 네오가 기억한 멜로디와 악보에 사용되는 음은 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개이다.
  • 각 음은 1분에 1개씩 재생된다. 음악은 반드시 처음부터 재생되며 음악 길이보다 재생된 시간이 길 때는 음악이 끊김 없이 처음부터 반복해서 재생된다. 음악 길이보다 재생된 시간이 짧을 때는 처음부터 재생 시간만큼만 재생된다.
  • 음악이 00:00를 넘겨서까지 재생되는 일은 없다.
  • 조건이 일치하는 음악이 여러 개일 때에는 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환한다. 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환한다.
  • 조건이 일치하는 음악이 없을 때에는 “(None)”을 반환한다.

접근방법

  1. 1분에 1개씩 재생되므로 시간을 분단위로 변경해서 구해준다.
  2. #이 들어간 상태로 일치 여부를 판단하려면 문자열 길이 나 #여부, 노래 반복 시 다른 문자열과 조합 등 문제가 발생할 가능성이 크니 없애준다.
  3. (중요) 문제에는 12개의 음으로 구분되어 있다고 하지만 자꾸 틀려서 알아보니 B# 음이 추가로 존재했다...

핵심로직

  1. C#, D#, F# 등을 c, d, f 와 같은 1글자의 소문자 형태로 변경
  2. 음악이 재생된 시간에 따라 총 연주된 음을 구함(반복 추가, 연주 중 잘리는 것 까지 고려)
  3. 조건이 일치하는 음악이 여러 개일 때 재생된 시간이 제일 긴 음악을 판단해야 하므로 재생 시간을 기록할 변수 활용

입출력 예

  • m = "ABCDEFG"
  • musicinfos = ["12:00,12:14,HELLO,CDEFGAB", "13:00,13:05,WORLD,ABCDEF"]
  • answer = "HELLO"

코드 작성(1차)

class Solution {
    public String solution(String m, String[] musicinfos) {
        String answer = "";
        int playTime = 0;
        m = m.replace("C#", "c");
        m = m.replace("D#", "d");
        m = m.replace("F#", "f");
        m = m.replace("G#", "g");
        m = m.replace("A#", "a");
        m = m.replace("B#", "b");

        for(int i=0; i<musicinfos.length; i++) {
            String[] musicInfo = musicinfos[i].split(",");
            String[] startTime = musicInfo[0].split(":");
            String[] endTime = musicInfo[1].split(":");
            int startMin = Integer.parseInt(startTime[0])*60 + Integer.parseInt(startTime[1]);
            int endMin = Integer.parseInt(endTime[0])*60 + Integer.parseInt(endTime[1]);
            
            String musicCode = musicInfo[3];
            musicCode = musicCode.replace("C#", "c");
            musicCode = musicCode.replace("D#", "d");
            musicCode = musicCode.replace("F#", "f");
            musicCode = musicCode.replace("G#", "g");
            musicCode = musicCode.replace("A#", "a");
            musicCode = musicCode.replace("B#", "b");
            
            String wholeMusic = "";
            for(int j=0; j<(endMin-startMin)/musicCode.length(); j++) {
                wholeMusic += musicCode;
            }
            wholeMusic += musicCode.substring(0, (endMin-startMin)%musicCode.length());
            
            if(wholeMusic.contains(m) && playTime < endMin-startMin) {
                answer = musicInfo[2];
                playTime = endMin-startMin;
            }
        }
        if(answer.length() == 0) {
            answer = "(None)";
        }
        return answer;
    }
}

중복되는 코드가 많고 변수명이 직관적이지 않아 리팩터링을 해준다.

코드 작성(2차)

class Solution {
    public String solution(String m, String[] musicinfos) {
        String answer = "(None)";
        int longestPlayTime = 0;
        
        // 샤프 음 처리를 위한 별도 함수화
        m = replaceSharpNotes(m);

        for (String musicinfo : musicinfos) {
            String[] musicDetails = musicinfo.split(",");
            int playTime = calculatePlayTime(musicDetails[0], musicDetails[1]);
            String musicTitle = musicDetails[2];
            String musicCode = replaceSharpNotes(musicDetails[3]);

            String playedMusic = createPlayedMusic(musicCode, playTime);

            // 멜로디가 포함되어 있고 재생 시간이 더 긴 곡이 있다면 answer을 갱신
            if (playedMusic.contains(m) && playTime > longestPlayTime) {
                answer = musicTitle;
                longestPlayTime = playTime;
            }
        }
        
        return answer;
    }

    // 샤프 음을 소문자로 변환하는 함수
    private String replaceSharpNotes(String melody) {
        return melody.replace("C#", "c")
                     .replace("D#", "d")
                     .replace("F#", "f")
                     .replace("G#", "g")
                     .replace("A#", "a")
                     .replace("B#", "b");
    }

    // 재생 시간을 계산하는 함수
    private int calculatePlayTime(String start, String end) {
        String[] startTime = start.split(":");
        String[] endTime = end.split(":");
        int startMinutes = Integer.parseInt(startTime[0]) * 60 + Integer.parseInt(startTime[1]);
        int endMinutes = Integer.parseInt(endTime[0]) * 60 + Integer.parseInt(endTime[1]);
        return endMinutes - startMinutes;
    }

    // 재생된 전체 음악을 생성하는 함수
    private String createPlayedMusic(String musicCode, int playTime) {
        StringBuilder playedMusic = new StringBuilder();
        int fullRepeats = playTime / musicCode.length();
        int remainingPart = playTime % musicCode.length();

        playedMusic.append(musicCode.repeat(fullRepeats))
                   .append(musicCode, 0, remainingPart);

        return playedMusic.toString();
    }
}
728x90
반응형