출처: https://school.programmers.co.kr/learn/courses/30/lessons/17683
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
🔎 풀이
문제의 조건이 많고 헷갈려서 먼저 문제를 정리해봤습니다.
방송된 곡의 정보 배열 musicinfos에는 음악 시작 시간, 음악 종료 시간, 음악 제목, 악보 정보가 ','로 구분된 String이 있습니다.
음악 재생 시간은 종료 시간 - 시작 시간인데, 재생 시간 > 악보의 길이 라면 악보가 반복 재생 된 것입니다.
재생 시간 < 악보 길이 라면 악보를 모두 재생하지 못하고 재생 시간 만큼만 재생이 된 것입니다.
그렇게 재생된 음악 중 네오가 들은 멜로디 m이 포함되어 있다면 네오가 그 음악을 들은 것입니다.
따라서 musicinfos 의 정보들을 가지고 재생 시간만큼 실제 재생된 멜로디를 구하고, 그 멜로디에 네오가 들은 멜로디가 포함되어 있다면 그 음악 이름을 저장합니다.
음악 이름이 여러 개가 나올 수 있는데, 그럴 때는 라디오의 재생 시간(음악 종료 시간 - 시작 시간)이 가장 긴 음악 제목을 반환합니다. 만약 재생 시간도 같다면 먼저 입력된 음악 제목을 반환합니다.
먼저 사용된 음에 #이 포함된 음도 있기 때문에 쉽게 비교해주기 위해서 #이 붙은 음은 소문자로 바꿔주는 작업을 했습니다. #이 붙은 음은 C#, D#, F#, G#, A# 밖에 없기 때문에 5종류를 소문자로 바꿔주는 함수를 만들었습니다.
public String replaceSharp(String str){
str = str.replaceAll("C#", "c");
str = str.replaceAll("D#", "d");
str = str.replaceAll("F#", "f");
str = str.replaceAll("G#", "g");
str = str.replaceAll("A#", "a");
return str;
}
musicinfos 배열을 돌면서 음악이 실제로 재생된 멜로디를 구해줍니다.
음악 시작 시간과 종료 시간으로 음악 재생 시간을 구합니다.
악보의 길이가 재생시간보다 짧다면 악보가 반복 재생된 것이기 때문에 악보를 반복해줍니다. 그리고 음악 재생 시간만큼 악보를 잘라줍니다. 그렇게 구한 악보가 실제로 재생된 멜로디입니다.
실제 재생된 멜로디에 네오가 들은 멜로디가 포함된다면 그 곡이 네오가 들은 음악입니다. 그 중 재생 시간이 가장 긴 음악의 제목을 반환해야 하기 때문에 time을 비교해서 가장 클 때의 음악 제목을 구해줍니다. 먼저 입력된 음악을 반환하게 하려면 max와 비교할 때 부등호에 =이 들어가지 않아야 합니다.
for(String musicinfo : musicinfos){
String[] infoArr = musicinfo.split(",");
// 음악 재생 시간 구하기
int startTime = Integer.valueOf(infoArr[0].substring(0, 2)) * 60 + Integer.valueOf(infoArr[0].substring(3, 5));
int endTime = Integer.valueOf(infoArr[1].substring(0, 2)) * 60 + Integer.valueOf(infoArr[1].substring(3, 5));
int time = endTime - startTime;
// 실제 재생 멜로디 구하기
String sheet = replaceSharp(infoArr[3]);
// 악보의 길이가 재생시간보다 짧다면 악보 반복해주기
if(sheet.length() < time){
sheet += sheet.repeat(time/sheet.length());
}
// 재생 시간만큼 악보 자르기
sheet = sheet.substring(0, time);
// 악보에 네오가 들은 멜로디가 포함되어 있다면 답
if(sheet.contains(m)){
// 재생 시간이 가장 긴 음악 제목으로
if(time > max){
max = time;
answer = infoArr[2];
}
}
}
만약 answer가 빈 문자열이라면 조건에 일치하는 음악이 없었던 것이기 때문에 (None)을 반환하고, 아닌 경우에는 answer를 반환합니다.
💡 소스코드
class Solution {
public String solution(String m, String[] musicinfos) {
String answer = "";
int max = 0;
m = replaceSharp(m);
for(String musicinfo : musicinfos){
String[] infoArr = musicinfo.split(",");
int startTime = Integer.valueOf(infoArr[0].substring(0, 2)) * 60 + Integer.valueOf(infoArr[0].substring(3, 5));
int endTime = Integer.valueOf(infoArr[1].substring(0, 2)) * 60 + Integer.valueOf(infoArr[1].substring(3, 5));
int time = endTime - startTime;
String sheet = replaceSharp(infoArr[3]);
if(sheet.length() < time){
sheet += sheet.repeat(time/sheet.length());
}
sheet = sheet.substring(0, time);
if(sheet.contains(m)){
if(time > max){
max = time;
answer = infoArr[2];
}
}
}
if(answer.length() == 0){
return "(None)";
}
return answer;
}
public String replaceSharp(String str){
str = str.replaceAll("C#", "c");
str = str.replaceAll("D#", "d");
str = str.replaceAll("F#", "f");
str = str.replaceAll("G#", "g");
str = str.replaceAll("A#", "a");
return str;
}
}
🍀 마치며...
이번 문제는 어렵다기보다는 조건이 헷갈려서 실수할 수 있는 문제인 것 같습니다. 지문을 읽고 손으로 예제를 직접 해보면서 조건을 이해하고 정리한 후에 문제를 푸는 습관이 도움이 많이 될 것 같습니다!
'Programming > Programmers' 카테고리의 다른 글
[프로그래머스] Lv2. 호텔 대실 (Java) (0) | 2023.07.22 |
---|---|
[프로그래머스] Lv2. 점 찍기 (Java) (0) | 2023.07.22 |
[프로그래머스] Lv2. 무인도 여행 (Java) (0) | 2023.07.14 |
[프로그래머스] Lv2. 두 큐 합 같게 만들기 (Java) (0) | 2023.07.13 |
[프로그래머스] Lv2. 쿼드압축 후 개수 세기 (Java) (0) | 2023.07.07 |