[Codekata] JavaScript

link717·2021년 1월 1일
0

codekata

목록 보기
5/5
post-thumbnail

😥 Question?

/*방금그곡 서비스에서는 음악 제목, 재생이 시작되고 끝난 시각, 악보를 제공한다.
네오가 기억한 멜로디와 악보에 사용되는 음은
C, C#, D, D#, E, F, F#, G, G#, A, A#, B 12개이다.

1) 각 음은 1분에 1개씩 재생된다. 음악은 반드시 처음부터 재생되며 음악 길이보다 재생된 시간이 길 때는 음악이 끊김 없이 처음부터 반복해서 재생된다.
2) 음악 길이보다 재생된 시간이 짧을 때는 처음부터 재생 시간만큼만 재생된다.
3) 음악이 00:00를 넘겨서까지 재생되는 일은 없다.
4) 조건이 일치하는 음악이 여러 개일 때에는 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환한다.
5) 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환한다.
6) 조건이 일치하는 음악이 없을 때에는 "(None)" 을 반환한다.*/


작성한 코드)
// sharp 변환
const changeSharp = (str) => {
  let _str = str.replace(/C#/g, "c").replace(/D#/g, "d").replace(/F#/g, "f").replace(/G#/g, "g").replace(/A#/g, "a")
  return _str;
}

// 시간 계산
const conversionTime = (start, end) => {
  return ((parseInt(end.substring(0,2)) - parseInt(start.substring(0,2))) * 60 + 
  (parseInt(end.substring(3)) - parseInt(start.substring(3)))) 
}

const solution = (m, musicinfos) => {
  let _m = changeSharp(m);
  let stack = [];
  
  // 재생시간에 따른 제목, 음계 정보
  for (let music of musicinfos) {
    let [start, end, title, notes] = music.split(",");
    let timeDiff = conversionTime(start, end);
    let _notes = changeSharp(notes);
    if (timeDiff <= _notes.length) {
      stack.push([title, _notes.slice(0, timeDiff)]);
    } else {
      let cycles = Math.floor(timeDiff/_notes.length);
      let restNotes = timeDiff%_notes.length;
      stack.push([title, _notes.repeat(cycles) + _notes.slice(0, restNotes)])
    }
  }
  
  // stack에 담긴 노래 중 조건부 음악 출력
  let filteredMusics = stack.filter(el => el[1].includes(_m));
  if (filteredMusics.length === 0) {
    return "(None)";
  } else if (filteredMusics.length === 1) {
    return filteredMusics[0][0];
  } else {
    let maxTime = 0;
    let answer = "";
    for (let i = 0; i < filteredMusics.length; i++) {
      if (filteredMusics[i][1].length > maxTime) {
        maxTime = filteredMusics[i][1].length;
        answer = filteredMusics[i][0];
      }  
    }
    return answer;
  }
}

😏 Idea!

1차로 작성했던 코드는 일부 케이스가 통과되지 않아 구글링으로 몇 가지 풀이 방법을 보고 이해해서 정리해보았다.

  • #이 붙은 음계의 경우, string 1개 = 재생시간 1분으로 처리할 수 있도록 replace를 사용하여 소문자 형태로 치환한다.
/*바꾸려는 패턴을 정규식 형태로 작성하지 않았을 경우,
바꾸려고 하는 문자를 전부 바꾸지 않고 첫번째 패턴만 치환한다.*/

const text = "C#C#ABC#";

console.log(text.replace("C#", "C"));  // 'CC#ABC#'
console.log(text.replace(/C#/g, "C")); // 'CCABC'
  • ,(comma)로 구분된 input을 split 한 뒤 destructuring assignment를 사용하여 각각의 변수로 담아주었다.
const music = "12:00,13:10,Hello,C#CABCD";
let [start, end, title, notes] = music.split(",");

console.log(start, end, title, notes); // '12:00' '13:10' 'Hello' 'C#CABCD'
  • "음악 길이보다 재생된 시간이 짧을 때는 처음부터 재생 시간만큼만 재생된다."의 조건에 맞추기 위해 repeat와 slice method를 사용하였다.
/* repeat는 string 뒤에 사용되며 입력된 count만큼
string을 반복하여 return 해준다.*/

const string = "ABC";
let _string = string.repeat(3);

console.log(string, _string); // 'ABC' 'ABCABCABC'

/* slice는 첫번째 인자로 start index를 받는다.
만약 index가 음수라면 strng의 length - index 위치로 인식한다.

두번째 인자로 end index를 받는다.(Option)
만약 두번째 값을 입력하지 않으면 문자열의 마지막 위치로 인식한다.
start-end index에 해당하는 string을 return 한다.*/

const string = "ABC";
let _string = string.slice(0, 1);

console.log(string, _string); // 'ABC' 'A'

// 둘 다 원본은 바뀌지 않는다.
profile
Turtle Never stop

0개의 댓글