[프로그래머스][JS]방금그곡

Kyle·2020년 12월 31일
0

problem solving

목록 보기
23/36

방금그곡

문제

문제: https://programmers.co.kr/learn/courses/30/lessons/17683#

문제가 길기 때문에 따로 설명은 안하겠습니다. 문제가 궁금하신 분들은 위의 링크를 타고가서 보세요~

해결방법

  1. musicinfos에는 시간과 원곡코드가 들어있기 때문에 저희가 필요한용도로 파싱(parser)해줍니다.
    ex) ["12:00,12:04,FOO,A#BC"] => [ {name:FOO, code:[A#,B,C,A#]} ]

  2. 만약 둘다 가능할 경우는 재생시간(code.length)에 비례하기 때문에 정렬해줍니다.

  3. checkCode: 내 기억(m)과 parse한 code를 비교해 결과를 도출합니다.

parser() 뮤직인포 파싱하기

  1. getTime(): 시간을 분으로 변경해 줍니다.
    • (시간끼리 뺀 값 * 60) + (분끼리 뺀 값)
  2. getFullCode(): 시간을 이용해서 시간에 맞는 코드를 구합니다.
    - tokenizeCode() '#"을 포함해서 나눠줘야 되기 때문에 문자열보다는 배열로 나눠줍니다.
    2-1. fullCode: 시간에 따라서 맞는 code배열을 반환합니다.
    - code.length === time
    - time < code.length
    - time > code.length
    2-2. 이름과, fullCode로 객체로 만들어 줍니다.

checkCode() m이 포함되는지 검사하기

내가 들은 기억(m)은 일부만 들어있어도 안되고 완전체가 다 들어있어야 합니다.

  1. codeLen: tokenize(m)으로 m의 코드배열의 길이를 구해줍니다.
  2. 이제 codeLen만큼 check할 코드에서 앞에서부터 slice해서 m과 같은지 검사해주면됩니다.
for (let i = 0; i <= fullCode.length - codeLen; i++) {
    if (fullCode.slice(i, i + codeLen).join("") === m) return true;
  }
  • 배열은 주소값을 비교하기 때문에 문자열로 바꾸어 주어서 m과 직접 비교해줍니다.
  • i부터 순회할 때 i뒤의 값이 codeLen보다 적게 남으면 검사할 필요가 없기 때문에 i <= fullCode.length - codeLen i의 조건을 이렇게 해줍니다.

code

function solution(m, musicinfos) {
  let musicInfos = parser(musicinfos);
  musicInfos.sort((a, b) => b.code.length - a.code.length);
  for (let musicInfo of musicInfos) {
    if (checkCode(musicInfo.code, m)) {
      return musicInfo.name;
    }
  }
  return `(None)`;
}

function parser(musicinfos) {
  const newMusicinfos = [];
  musicinfos.forEach((musicinfo) => {
    const [startTime, endTime, name, code] = musicinfo.split(",");
    const time = getTime(startTime, endTime);
    const fullCode = getFullCode(time, code);
    newMusicinfos.push({ name, code: fullCode });
  });
  return newMusicinfos;
}

function getTime(start, end) {
  start = start.split(":").map((v) => v * 1);
  end = end.split(":").map((v) => v * 1);
  const hours = end[0] - start[0];
  const minutes = end[1] - start[1];
  return hours * 60 + minutes;
}

function getFullCode(time, code) {
  code = tokenizeCode(code);
  let newCode = [];
  if (code.length === time) newCode = code;
  else if (time < code.length) newCode = code.slice(0, time);
  else {
    for (let i = 0; i < time; i++) {
      newCode.push(code[i % code.length]);
    }
  }
  return newCode;
}
function tokenizeCode(code) {
  code = code.split("");
  for (let i = 0; i < code.length; i++) {
    if (code[i] === "#") {
      code[i - 1] += "#";
      code.splice(i, 1);
      i--;
    }
  }
  return code;
}

function checkCode(fullCode, m) {
  const codeLen = tokenizeCode(m).length;
  for (let i = 0; i <= fullCode.length - codeLen; i++) {
    if (fullCode.slice(i, i + codeLen).join("") === m) return true;
  }
  return false;
}

마무리

코드가 매우 길다...
처음부터 자세하게 설계하기 보다는 큰 가닥이 그려져서 코딩을 이어갔는데 그것 때문인 것 같다. 설계를 조금 더 디테일하게 하면 구현도 더 빠른시간내에 할 수 있을 것이라 생각된다.
다음부터는 코드 설계를 더 디테일하게 하고 구현해봐야겠다.

profile
Kyle 발전기

0개의 댓글