[프로그래머스] 방금그곡 (Java)
문제
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
알고리즘
없음
풀이
재생된 시간만큼 musicinfo의 악보를 확장하여 멜로디 m이 포함되어있는지 확인하면 된다.
하지만 악보에 사용되는 음이 C, C# 처럼 #이 붙은 음이 있어 ABC#이라는 악보와 ABC라는 멜로디가 있다면 ABC#에 ABC가 포함된 것으로 잘못된 결과가 나올 수 있다.
따라서 이를 해결하기 위해 #이 들어간 음을 다른 문자로 변경하였다.
C# - 3, D# - 4, F# - 6, G# - 7, A# - 1
이 방법으로 ABC# 은 AB3 이 되고, ABC 라는 멜로디와 구분될 수 있다.
1. 멜로디 m의 #을 숫자로 변환
2. 음악이 재생된 시간 계산
3. 악보의 #을 숫자로 변환
4. 악보를 재생된 길이만큼 확장
5. 확장시킨 악보에 변환된 m이 포함되어 있는지 확인
1. 멜로디 m의 #을 숫자로 변환
m의 각 글자를 탐색하며 해당 글자의 다음 글자가 #이라면 두 글자를 합쳐서
A#은 1로, C#은 3과 같은 형식으로 변환한다.
이때 문자열이 계속 수정되기 때문에 StringBuilder를 사용한다.
2. 음악이 재생된 시간 계산
StringTokenizer를 이용해 ":" 로 시간과 분을 구분하여
(시작시간 * 60 + 시작분) - (종료시간 * 60 + 종료분) 로 음악이 재생된 시간을 계산한다.
3. 악보의 #을 숫자로 변환
1과 동일하게 변환한다.
4. 악보를 재생된 길이만큼 확장
만약 재생된 길이가 17, 악보의 길이가 4라면 해당 악보가 4번 반복되고 악보의 첫 음이 재생될 것이다.
즉 (재생된 길이 / 악보의 길이) 번 악보를 붙이고, (재생된 길이 % 악보의 길이) 글자만큼 추가로 붙이면
확장된 악보를 얻을 수 있다.
5. 확장시킨 악보에 변환된 m이 포함되어 있는지 확인
확장시킨 악보에 변환된 m이 포함되어있는지 확인하는데 StringBuilder는 contains() 메소드가 없기 때문에 대신 indexOf() 메소드를 사용한다.
indexOf(string)은 string이 있다면 index를, 없다면 -1을 반환한다.
따라서 악보.indexOf(멜로디)의 반환값이 -1이 아니고 재생 시간이 최대 재생 시간보다 길다면
정답과 최대 재생 시간을 갱신한다.
* 일치하는 음악이 없으면 "(None)" 을 반환해야하므로 answer를 "(None)"으로 초기화해둔다.
코드
import java.util.*;
class Solution {
public String solution(String m, String[] musicinfos) {
String answer = "(None)";
int answerTime = 0;
StringBuilder conM = convert(m);
for(String musicinfo: musicinfos) {
StringTokenizer st = new StringTokenizer(musicinfo, ",");
int time = getTime(st.nextToken(), st.nextToken());
String title = st.nextToken();
StringBuilder acbo = convert(st.nextToken());
StringBuilder extAcbo = extend(acbo.toString(), time);
if(extAcbo.indexOf(conM.toString()) != -1 && time > answerTime) {
answer = title;
answerTime = time;
}
}
return answer;
}
public int getTime(String start, String end) {
StringTokenizer st = new StringTokenizer(start, ":");
int startm = Integer.parseInt(st.nextToken()) * 60 + Integer.parseInt(st.nextToken());
st = new StringTokenizer(end, ":");
int endm = Integer.parseInt(st.nextToken()) * 60 + Integer.parseInt(st.nextToken());
return endm - startm;
}
public StringBuilder convert(String string) {
StringBuilder sb = new StringBuilder();
for(int i=0; i<string.length(); i++) {
if(i < string.length()-1 && string.charAt(i + 1) == '#') {
sb.append((char)(string.charAt(i) - 'A' + '1'));
i++;
}
else sb.append(string.charAt(i));
}
return sb;
}
public StringBuilder extend(String string, int time) {
StringBuilder sb = new StringBuilder();
for(int i=0; i<time/string.length(); i++)
sb.append(string);
for(int i=0; i<time%string.length(); i++)
sb.append(string.charAt(i));
return sb;
}
}