프로그래머스/자바 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개씩 재생되므로 시간을 분단위로 변경해서 구해준다.
- #이 들어간 상태로 일치 여부를 판단하려면 문자열 길이 나 #여부, 노래 반복 시 다른 문자열과 조합 등 문제가 발생할 가능성이 크니 없애준다.
- (중요) 문제에는 12개의 음으로 구분되어 있다고 하지만 자꾸 틀려서 알아보니 B# 음이 추가로 존재했다...
핵심로직
- C#, D#, F# 등을 c, d, f 와 같은 1글자의 소문자 형태로 변경
- 음악이 재생된 시간에 따라 총 연주된 음을 구함(반복 추가, 연주 중 잘리는 것 까지 고려)
- 조건이 일치하는 음악이 여러 개일 때 재생된 시간이 제일 긴 음악을 판단해야 하므로 재생 시간을 기록할 변수 활용
입출력 예
- 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
반응형