[java] 프로그래머스 - 방금그곡
업데이트:
문제
프로그래머스-방금그곡
방송된 곡 정보 배열에서 내가 기억하는 멜로디를 담은 노래를 찾는 문제
네오가 기억한 멜로디와 악보에 사용되는 음은 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개이다
- 제한 사항
네오가 기억하는 멜로디 m
: 1 <= m
<= 1439
곡 정보를 담고있는 배열 musicinfos
: musicinfos길이
<= 100
음악의 시작 시간, 끝난 시간은 HH:MM
형식
음악 제목 : 1 <= 음악제목 <= 64 길이의 문자열
악보 정보 : 1 <= 음 <= 1439
- 예시
m : “ABCDEFG”
musicinfos : [12:00,12:14,HELLO,CDEFGAB, 13:00,13:05,WORLD,ABCDEF]
첫번째 곡은 14분간 재생되므로 CDEFGAB(길이 7)가 2번 반복된다
-> CDEFGABCDEFGAB
두번째 곡은 5분간 재생되므로 ABCDEF(길이 6)에서 5만큼 자른다
-> ABCDE
첫번째 곡이 m
을 다 포함하고 있으므로 첫번째 곡의 제목인 “HELLO”가 답이된다
풀이
조건에 해당하는 곡이 여러개라면 재생시간이 제일 긴 음악을,
재생 시간도 같다면 먼저 입력된 음악 제목을 반환해야 하므로 Music
이라는 객체를 만들어서 사용했다
- Music
class Music { int idx; // 입력 순서 int duration; // 재생 시간(분) String title; // 제목 String totalMelody; // 재생시간에 따른 멜로디 }
재생시간은 시작시간과 종료시간을 가지고 시(hour)가 같으면 분으로 차이를 구하고 시가 다르면 다른만큼 60을 곱해 분을 계산했다
멜로디는 재생시간보다 입력받은 멜로디가 크면 subString(0, 재생시간)
멜로디가 작으면 클때까지 멜로디를 더해서 subString(0, 재생시간) 한다
악보에 사용하는 음이 C, C#, D, D#, E, F, F#, G, G#, A, A#, B 이렇게 12종류여서
C#은 2자리 문자열이지만 하나로 처리해서 확인해야한다
C#은 c, D#은 d, … 이런식으로 #이붙은 음은 소문자로 변경해서 한자리 문자열로 사용했다
그래야 비교할 문자열 m
을 music.totalMelody.contains(m)
로 포함여부를 확인하기 쉬우니까~~
마지막에 조건을 만족하는 곡이 여러개일때 정렬해서 하나를 뽑았는데
그냥 max같은 값 두고 갱신하면서 해도 괜찮았을거같다
소스코드
import java.util.*;
class Solution {
public String solution(String m, String[] musicinfos) {
String mem = convertedMelody(m);
LinkedList<Music> musics = new LinkedList<>();
for (int i = 0; i < musicinfos.length; i++) {
String[] t = musicinfos[i].split(",");
Music music = new Music(i, getDiffSec(t[0], t[1]), t[2], convertedMelody(t[3]));
if (music.totalMelody.length() >= mem.length() && music.totalMelody.contains(mem))
musics.add(music);
}
if (musics.size() > 0) {
musics.sort(new Comparator<Music>() {
@Override
public int compare(Music o1, Music o2) { // 재생시간 긴 순, 인덱스 작은순
if (o2.duration == o1.duration) {
return o1.idx - o2.idx;
}
return o2.duration - o1.duration;
}
});
Music ans = musics.pollFirst();
return ans.title;
} else {
return "(None)"; // 곡이 검색되지 않은 경우
}
}
private int getDiffSec(String t1, String t2) { // 시간차이 구하기
String time1[] = t1.split(":");
String time2[] = t2.split(":");
if (time1[0].equals(time2[0])) {
return Integer.parseInt(time2[1]) - Integer.parseInt(time1[1]);
}
int h = Integer.parseInt(time2[0]) - Integer.parseInt(time1[0]);
return (60 * h + Integer.parseInt(time2[1])) - Integer.parseInt(time1[1]);
}
private String convertedMelody(String m) {
m = m.replaceAll("C#", "c");
m = m.replaceAll("D#", "d");
m = m.replaceAll("F#", "f");
m = m.replaceAll("G#", "g");
m = m.replaceAll("A#", "a");
return m;
}
}
class Music {
int idx;
int duration;
String title;
String totalMelody;
public Music(int idx, int duration, String title, String melody) {
super();
this.idx = idx;
this.duration = duration;
this.title = title;
this.totalMelody = makeFullMelody(melody, this.duration);
}
private String makeFullMelody(String me, int d) {
if (me.length() > d)
return me.substring(0, d);
StringBuilder sb = new StringBuilder();
while (sb.length() < d) {
sb.append(me);
}
return sb.toString().substring(0, d);
}
}
댓글남기기