✔ 방금그곡
문제 분석하기
음악 재생시간만큼 곡 정보의 멜로디를 변환하여 네오가 기억한 멜로디와 같을 경우 저장함
이후 같은 음악이 없으면 (None)을 반환
같은 음악이 있으며, 조건이 일치하는 음악이 여러 개일 때는 길이가 가장 긴 음악을 반환
이때 길이도 같다면 인덱스가 앞인 음악을 반환
손으로 풀어보기
- 방속된 곡과 네오가 기억한 멜로디를 변환
- C
- C# → H
- D
- D# → I
- E
- F
- F# → J
- G
- G# → K
- A
- A# → L
- B
- 방송된 곡의 멜로디 정보를 가지고 음악이 재생된 시간만큼 멜로디를 다시 저장
- 네오가 기억한 멜로디를 담은 곡과 일치하는지 확인한 후 일치할 경우 리스트에 저장
- 조건이 일치하는 음악이 없을 경우 None을 반환
- 조건이 일치하는 음악 있을 경우 이를 반환
- 음악을 음악 재생 시간과 인덱스에 따라 정렬
- 리스트 가장 앞의 음악의 제목을 반환
슈도코드 작성하기
m(네오가 기억하는 멜로디를 담은 문자열)
musicinfos(방송된 곡의 정보를 담고 있는 배열)
list(일치하는 음악 정보를 저장할 리스트)
m의 멜로디를 변환
일치하는 음악 저장하기 함수(m, musicinfos)
if(list가 비어있다면) {
(None) 반환
}
list 정렬
list.get(0)의 name을 반환
일치하는 음악 저장하기 함수 {
for(info -> infos만큼) {
arr(info의 정보를 담은 문자열 배열)
time(음악 재생 시간) = 음악 재생 시간 구하기 함수(음악이 시작한 시각, 끝난 시각)
name(음악 제목)
melody(음악 악보)
melody의 멜로디를 변환
sb(StringBuilder)에 time만큼 melody를 반복하여 저장
if(melody에 m이 포함된다면)
리스트에 일치하는 음악 저장
}
}
멜로디 변환하기 함수 {
#이 붙은 음계를 다른 음으로 변환
변환된 멜로디를 반환
}
음악 재생 시간 구하기 함수 {
start(음악이 시작한 시간 초)
end(끝난 시간 초)
end - start 반환
}
music {
name(음악 제목)
melody(음악 악보)
time이 같을 경우 인덱스로 비교하는 커스텀 정렬 코드 작성
}
코드 구현하기
/**
* 17683) 방금그곡
*/
public class L031_17683 {
// 음악
class Music implements Comparable<Music> {
// name(음악 제목)
String name;
// melody(음악 악보)
String melody;
Music(String name, String melody) {
this.name = name;
this.melody = melody;
}
// time이 같을 경우 인덱스로 비교하는 커스텀 정렬 코드 작성
@Override
public int compareTo(Music m) {
// melody의 길이(재생된 시간)가 같다면
if (this.melody.length() == m.melody.length()) {
// 먼저 입력된 음악 제목이 우선
return Integer.compare(list.indexOf(this), list.indexOf(m));
}
// melody의 길이(재생된 시간)이 긴 음악 제목이 우선
return Integer.compare(m.melody.length(), this.melody.length());
}
}
// list(일치하는 음악 정보를 저장할 리스트)
static List<Music> list;
// m(네오가 기억하는 멜로디를 담은 문자열)
// musicinfos(방송된 곡의 정보를 담고 있는 배열)
public String solution(String m, String[] musicinfos) {
list = new ArrayList<>();
// m의 멜로디를 변환
m = changeMelody(m);
// 일치하는 음악 저장하기 함수(m, musicinfos)
saveCorrectMusic(m, musicinfos);
// list가 비어있다면
if (list.isEmpty())
// (None) 반환
return "(None)";
// list 정렬
Collections.sort(list);
// list.get(0)의 name을 반환
return list.get(0).name;
}
// 일치하는 음악 저장하기 함수
private void saveCorrectMusic(String m, String[] infos) {
for (String info : infos) {
// arr(info의 정보를 담은 문자열 배열)
String[] arr = info.split(",");
// time(음악 재생 시간) = 음악 재생 시간 구하기 함수(음악이 시작한 시각, 끝난 시각)
int time = calculateTime(arr[0], arr[1]);
// name(음악 제목)
String name = arr[2];
// melody(음악 악보)
String melody = arr[3];
// melody의 멜로디를 변환
melody = changeMelody(melody);
// sb(StringBuilder)에 time만큼 melody를 반복하여 저장
StringBuilder sb = new StringBuilder();
for (int i = 0, j = 0; i < time; i++, j = (j + 1) % melody.length()) {
sb.append(melody.charAt(j));
}
melody = sb.toString();
// melody에 m이 포함된다면
if (melody.contains(m))
// 리스트에 일치하는 음악 저장
list.add(new Music(name, melody));
}
}
// 멜로디 변환하기 함수
private String changeMelody(String melody) {
// #이 붙은 음계를 다른 음으로 변환
melody = melody.replaceAll("C#", "H");
melody = melody.replaceAll("D#", "I");
melody = melody.replaceAll("F#", "J");
melody = melody.replaceAll("G#", "K");
melody = melody.replaceAll("A#", "L");
// 변환된 멜로디를 반환
return melody;
}
// 음악 재생 시간 구하기 함수
private int calculateTime(String time1, String time2) {
// start(음악이 시작한 시간 초)
int start = 60 * Integer.parseInt(time1.substring(0, 2)) + Integer.parseInt(time1.substring(3));
// end(끝난 시간 초)
int end = 60 * Integer.parseInt(time2.substring(0, 2)) + Integer.parseInt(time2.substring(3));
// end - start 반환
return end - start;
}
// 테스트 케이스
public static void main(String[] args) {
L031_17683 solution = new L031_17683();
String m = "ABC";
String[] musicinfos = {
"12:00,12:14,HELLO,C#DEFGAB",
"13:00,13:05,WORLD,ABCDEF" };
String result = solution.solution(m, musicinfos);
System.out.println(result);
}
}
'Coding Test > Java 알고리즘 실전' 카테고리의 다른 글
[17686] 파일명 정렬 (0) | 2024.01.15 |
---|---|
[17684] 압축 (0) | 2024.01.15 |
[17680] 캐시 (0) | 2024.01.14 |
[17679] 프렌즈4블록 (0) | 2024.01.14 |
[17677] 뉴스 클러스터링 (0) | 2024.01.13 |