[2018 카카오 블라인드] 방금그곡 (JAVA)

Jiwoo Kim·2021년 3월 9일
0
post-thumbnail

문제


풀이

오늘도 카카오 삽질대장정..☆ #에 따른 음 처리와 인덱스가 꼬이는 바람에 시간이 오래 걸렸다.

이 문제를 풀면서 느낀 건, 메소드는 간단하면 간단할 수록, 명료하면 명료할 수록 좋다는 점이다. 메소드 하나에 구구절절 끼워넣으니 디버깅하다가 머리 터질 뻔했는데, 최대한 분리하고 한 메소드에서 하나의 일만 하도록 하니까 정리가 되면서 문제가 풀렸다. 앞으로도 조건들을 하나의 문장이나 메소드에 끼워 넣지 말고 차근차근 나눠가며 풀면 더 빨리 그리고 정확하게 풀 수 있을 것 같다.

그리고 조건들을 확인하는 순서도 중요한 것 같다. if문 여러 개가 중첩으로 쌓이면 당연히 놓치는 조건이 발생하고 통과하지 않는 테스트 케이스가 생겨버린다. 분기문을 최소한으로 나누고 순서를 잘 고려하도록 항상 여러번 점검해야겠다.


  1. parseMusicInfos(): 주어진 musicInfos를 파싱해서 Music 리스트에 저장한다.

    • 간단하게 String split() 메소드를 사용했다. 음악 제목에 쉼표(,)가 없다는 조건이 있었기에 사용할 수 있었다.
    • 문제풀이에 필요한 필드인 playNotes, originalNotesMusic 생성자에서 파싱하도록 했다.
  2. findTargetMusic(): 주어진 m을 포함하고 있는 음악을 musics를 차례로 탐색하며 찾는다.
    a. startIndexendIndex를 가지고 음악의 부분음인 subNotes를 구하고, targetNotes와 비교한다.

    • 이 때 부분음의 길이는 calcNoteLength()에서 구한다. 그냥 String length()로 하면 # 처리때문에 답이 맞지 않는다.

    b. 일치하는 음악이 여러 개인 경우 isUpdatable()에서 조건을 체크해서 가장 최적인 음악으로 갱신한다.

  3. 찾아진 것이 없으면 (None)을, 있으면 음악 제목을 리턴한다.


코드

import java.util.*;

class Solution {   
    
    private List<Music> musics = new ArrayList<>();

    public String solution(String m, String[] musicInfos) {
        parseMusicInfos(musicInfos);
        Music result = findTargetMusic(m);
        if (result == null) return "(None)";
        return result.title;
    }

    private void parseMusicInfos(String[] musicInfos) {
        for (String musicInfo : musicInfos) {
            String[] chunks = musicInfo.split(",");
            musics.add(new Music(chunks[0], chunks[1], chunks[2], chunks[3]));
        }
    }

    private Music findTargetMusic(String targetNotes) {
        Music result = null;
        for (Music music : musics)
            if (isTargetAndMusicMatch(targetNotes, music))
                if (result == null || isUpdatable(result, music))
                    result = music;
        return result;
    }

    private boolean isTargetAndMusicMatch(String targetNotes, Music music) {
        int startIndex = 0, endIndex = calcNoteLength(targetNotes) - 1;
        while (endIndex < music.playedDuration) {
            String subNotes = music.getSubNotes(startIndex, endIndex);
            if (targetNotes.equals(subNotes)) return true;
            startIndex++;
            endIndex++;
        }
        return false;
    }

    private int calcNoteLength(String notes) {
        int count = 0;
        for (int i = 0; i < notes.length(); i++) {
            count++;
            if (i + 1 < notes.length() && notes.charAt(i + 1) == '#') i++;
        }
        return count;
    }
    
    private boolean isUpdatable(Music result, Music music) {
        if (music.playedDuration > result.playedDuration) return true;
        return musics.indexOf(music) < musics.indexOf(result);
    }
}

class Music {
    int startTime;
    int endTime;
    int playedDuration;
    String title;
    List<String> originalNotes;
    List<String> playedNotes;

    public Music(String startTime, String endTime, String title, String notes) {
        this.startTime = parseTime(startTime);
        this.endTime = parseTime(endTime);
        playedDuration = this.endTime - this.startTime;
        this.title = title;
        this.originalNotes = parseOriginalNotes(notes);
        this.playedNotes = getPlayedNotes();
    }

    private int parseTime(String timeStr) {
        String[] time = timeStr.split(":");
        int hour = Integer.parseInt(time[0]);
        int minute = Integer.parseInt(time[1]);
        return hour * 60 + minute;
    }

    private List<String> parseOriginalNotes(String notes) {
        List<String> result = new ArrayList<>();
        String note;
        for (int i = 0; i < notes.length(); i++) {
            note = notes.charAt(i) + "";
            if (i + 1 < notes.length() && notes.charAt(i + 1) == '#') {
                note += "#";
                i++;
            }
            result.add(note);
        }
        return result;
    }

    private List<String> getPlayedNotes() {
        List<String> result = new ArrayList<>();
        if (this.playedDuration > this.originalNotes.size()) {
            for (int i = 0; i < this.playedDuration / this.originalNotes.size(); i++)
                result.addAll(originalNotes);
            for (int i = 0; i < this.playedDuration % this.originalNotes.size(); i++)
                result.add(this.originalNotes.get(i));
        } else {
            for (int i = 0; i < this.playedDuration; i++)
                result.add(this.originalNotes.get(i));
        }
        return result;
    }
    
    public String getSubNotes(int startIndex, int endIndex) {
        StringBuilder sb = new StringBuilder();
        for (int i = startIndex; i <= endIndex; i++)
            sb.append(this.playedNotes.get(i));
        return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Music)) return false;
        Music music = (Music) o;
        return Objects.equals(title, music.title);
    }

    @Override
    public int hashCode() {
        return Objects.hash(title);
    }
}

0개의 댓글