처리조건
풀이
입력값 : solution("ABCDEFG", ["12:00,12:14,HELLO,CDEFGAB", "13:00,13:05,WORLD,ABCDEF"]);
우선 musicinfos를 받아 map를 활용해 각 요소마다 elString으로 split(",")를 사용해 , 를 기준으로 나누어 주었다.
입력값을 기준으로 아래처럼 나누어진다.
여기서 우리는 시간이 12:00~ 12:14 처럼 뒤에 시간의 분에서 앞에 시간의 분을 빼면 총 분을 구하는게 쉽지만 만약에 12:30~13:20 이렇게 된다면 단순히 분만 빼주는 것으론 총 분을 구할 수 없다. 그래서 뒤 시간의 시간이 앞 시간의 시간보다 크다면 60에서 앞시간의 분을 빼주고 거기에 뒷 시간의 분을 더하는 식으로 계산하도록 하였다. slice를 사용했고 allcount로 총 가동 분을 받게 된다.
이후에 allcount에 따라 인덱스3에 위치한 알파벳들을 만들어줄 것이다. allcount보다 해당하는 알파벳길이가 크거나 같으면 alllcount를 뺀 만큼을 현 알파벳길이에서 pop할것이고 다시 인덱스3에 할당한다. 그 밖에는 allcount에서 인덱스3의 길이를 나눠떨어지면 길이만큼 현알파벳을 repeat하여 더하고 나머지가 남으면 나머지만큼 한번 더 더한다. 그리고 이후에 인덱스1에 위치한 음악이름, 총 분 , 만들어진 알파벳을 배열에 담아 리턴한다.
지금까지 작성한 코드는 아래와 같다.
function solution(m, musicinfos) {
const arr = musicinfos.map((elString) => {
let splitEl = elString.split(",");
console.log(splitEl);
let allcount = 0;
if (Number(splitEl[0].slice(0, 2)) < Number(splitEl[1].slice(0, 2))) {
allcount = 60 - Number(splitEl[0].slice(3)) + Number(splitEl[1].slice(3));
} else {
allcount = Number(splitEl[1].slice(3)) + Number(splitEl[0].slice(3));
}
if (allcount <= splitEl[3].length) {
let deleteCnt = splitEl[3].length - allcount;
for (let i = 0; i < deleteCnt; i++) {
let temp = splitEl[3].split("");
temp.pop();
temp = temp.join("");
splitEl[3] = temp;
}
} else {
let desiCnt = Math.floor(allcount / splitEl[3].length);
let plusString = splitEl[3];
if (allcount % splitEl[3].length === 0) {
for (let i = 0; i < desiCnt - 1; i++) {
splitEl[3] += plusString;
}
} else if (allcount % splitEl[3].length !== 0) {
for (let i = 0; i < desiCnt - 1; i++) {
splitEl[3] += plusString;
}
splitEl[3] += plusString.slice(0, allcount % plusString.length).join("");
}
}
return [splitEl[2], allcount, splitEl[3]];
});
console.log(arr);
}
여기서 문제가 발생했다. 앞전에 인덱스3에 위치한 알파벳들이 #이들어가는 경우 하나로 묶어 하나의 분으로 계산해야한다는것이다. 예를 들어 ABCDE가 있다면 그냥 5개로 볼수 있지만 A#BCDE이렇게 돼있다면 A#은 한 음악기호로 본다.
그러면 총 분도 달라질 것이고 결과도 달라질 것이다.
const arr = musicinfos.map((mi) => {
const [start, end, title, code] = mi.split(",");
const hour = end.slice(0, 2) - start.slice(0, 2);
const minute = end.slice(3) - start.slice(3);
const runtime = 60 * hour + minute;
const codeArr = code.match(/[A-Z]#?/g);
let stream = code.repeat(Math.floor(runtime / codeArr.length));
stream += codeArr.slice(0,runtime % codeArr.length).join("");
return [title, runtime, stream];
});
로직을 바꾸었다. 효율적이고 가독성을 높이기 위해 검색을 해보았고 제일 깔끔하였다. 3번인덱스로 오는 code를 match를 통해 #이 붙은것을 예외 처리하여 codeArr로 인덱스를 가진 배열형태를 만들어준다.
이후 인자로 받은 m이랑 일치하는게 있는지 검색하게 되는데 arr을 찍어보면 아래와 같다.
m과 일치하는지 검색하고 가장 긴 분의 음악이름을 리턴하는 코드이다.
const answer = arr.filter(([_, __, stream]) => {
let i = stream.indexOf(m);
if (i === -1) return false;
while (i !== -1) {
if (stream[i + m.length] !== "#") return true;
i = stream.indexOf(m, i + 1);
}
});
if (!answer.length) return "(None)";
answer.sort((a, b) => {
if (a[1] === b[1]) return 0;
return b[1] - a[1];
});
return answer[0][0];
stream으로 각 arr의 요소마다 알파벳이 들어오게 될 것이다. indexOf로 m을 검색하여 위치한 인덱스 번호를 받고 #과 관계없이 아예 없다면 false를 리턴하여 최종적인 answer에 담지않게된다. 그외에 while문 돌려 i가 -1이 아닐때 까지만 돌리게 된다. stream의 인덱스 번호로 현재 m의 위치에 m의 길이만큼더하면 m을 찾은 다음 m의 다음번째가 된다. 이것이 #이 아닐시 맞아떨어진것이니 true를 리턴해 answer에 담는다. 만약 #이라면 m을 찾기시작한 인덱스를 1올려서 다시 m을 찾는다 못찾을시 i는 -1이 되고 또 i+1를 하여 검색되는 m이 있다면 다시 뒤에 #이있는지 확인.. 반복 결국엔 indexOf가 -1이 나와 없으면 최종적으로 false 가 리턴된다.
아래에서 찾은 answer이 하나도없다면 조건에 맞는게 없다는 것으로 처리하고
있다면 sort하여 각 요소의 1번인덱스인 총 분을 계산하여 높은순으로 맨앞으로 옮긴다. 그리고 해당하는 맨 앞 이름을 리턴한다.
'일반 학습 > 코딩 테스트' 카테고리의 다른 글
[프로그래머스] 파일명 정렬 (0) | 2022.03.11 |
---|---|
[프로그래머스] 압축 (0) | 2022.03.10 |
[프로그래머스] 캐시 (0) | 2022.03.09 |
[프로그래머스] 프렌드 4블록 (0) | 2022.03.09 |
[프로그래머스] 순위 검색 (0) | 2022.03.08 |
댓글