[Programmers Lv.2 | JS] 방금그곡

Bori·2023년 9월 18일
0

Algorithm

목록 보기
25/26
post-thumbnail

프로그래머스 방금그곡 문제 링크

나의 풀이

/* constants */
const REG_EXP = /(C|D|F|G|A)#/g;
const NONE = "(None)"

/* HH:MM 형식의 시간을 분 단위로 변환 */
const getMinutesTime = (time) => {
  const [hour, minute] = time.split(':');

  return (Number(hour) * 60) + Number(minute);
}

/* 음악 재생 시간 반환 */
const getPlayTime = (start, end) => {
  const startTime = getMinutesTime(start);
  const endTime = getMinutesTime(end);

  return endTime - startTime;
}

/* 실제 재생된 음악 정보 반환 */
const getPlayMusic = (musicNotes, playTime) => {
  let playMusic = musicNotes;
  const musicLength = playMusic.length;
  const repeatCount = Math.ceil(playTime / musicLength);

  // 음악 정보의 길이가 음악 재생 시간보다 적을 경우
  if (musicLength < playTime) {
    // 음악 정보를 repeatCount 만큼 반복
    playMusic = musicNotes.repeat(repeatCount);
  }

  // 실제 음악이 재생된 시간만큼 음악 정보 길이를 잘라서 반환
  return playMusic.slice(0, playTime + repeatCount);
}

/* 악보에 사용되는 음 중 # 기호가 포함된 음일 경우, 영소문자로 변환 */
const getReplaceMusicNotes = (musicNotes) => {
  return musicNotes.replace(REG_EXP, (_, match) => match.toLowerCase());
}

function solution(m, musicinfos) {
  const answer = new Map();
  const neoMusicNotes = getReplaceMusicNotes(m);

  musicinfos.forEach((musicInfo) => {
    const [startTime, endTime, title, music] = musicInfo.split(',');
    const musicNote = getReplaceMusicNotes(music);
    const playTime = getPlayTime(startTime, endTime);
    const playMusic = getPlayMusic(musicNote, playTime);

    if (playMusic.includes(neoMusicNotes)) {
      answer.set(title, playTime);
    }
  })

  const sortedAnswer = [...answer].sort((a, b) => {
    const aPlayTime = a[1];
    const bPlayTime = b[1];

    if(aPlayTime > bPlayTime) return -1;
    if(aPlayTime < bPlayTime) return 1;
    return 0;
  });

  // 조건이 일치하는 음악이 없는 경우 "(None)"을 반환
  // 조건이 일치하는 음악이 있는 경우  sortedAnswer의 첫 번째 요소의 title을 반환
  return answer.size === 0 ? NONE : sortedAnswer[0][0];
}

풀이 설명

처음 생각했던 풀이에서는 악보 내 # 기호의 갯수를 포함하여 재생된 음악의 악보를 구했습니다. 이 후 네오가 기억하는 멜로디가 재생된 음악의 악보에 includes를 이용하여 포함 여부를 확인하여 답을 구하는 과정을 구상했습니다.

이 때 문제점은 악보가 ABC#DEF 이고 네오가 기억하는 멜로디가 ABC일 경우, true를 반환한다는 점입니다.
따라서, # 기호가 포함된 음의 경우 다른 글자로 변환(위 풀이에서 영소문자로 변환)하여 구분될 수 있도록 했습니다.

# 기호가 포함된 음을 영소문자로 변환하는 과정에서 replace를 사용했는데 다른 분의 풀이를 통해 replace를 다음과 같이 사용할 수 있다는 것을 알게 되었습니다.

String.prototype.replace()

replace 메서드는 문자열의 패턴이 일치한다면 새로운 문자열로 반환할 수 있도록 합니다.

// Syntax
replace(pattern, replacement)
  • pattern
    • 문자열 또는 정규표현식에 일치하는 패턴을 대상 문자열에서 검색합니다.
    • 문자열을 사용할 경우, 첫 번째 검색 결과만 대체됩니다.
    • 정규표현식을 사용할 경우, 다양한 방식으로 검색할 수 있습니다.
  • replacement
    • 문자열 또는 함수를 적용할 수 있습니다.
    • 문자열인 경우, 패턴과 일치하는 문자열을 새로운 문자열을 대체합니다.
    • 함수인 경우, 패턴과 일치할 때마다 호출되고 반환값이 대체 텍스트로 사용됩니다.

replacement에 대체 함수 지정

// Syntax
function replacer(match, p1, p2, /* …, */ pN, offset, string, groups) {
  return replacement;
}
  • match
    • 정규표현식에 매치된 문자열을 나타냅니다.
  • p1, p2, ..., pn
    • 정규표현식에서 괄호로 묶은 그룹이 있다면, 각 그룹에 대한 매개변수가 순서대로 제공됩니다.
    • 첫 번째 그룹은 p1, 두 번째 그룹은 p2, ... 순차적으로 pn에 매칭된 값을 전달받습니다.
  • offset
    • 매치된 문자열이 원본 문자열에서 시작하는 인덱스를 나타냅니다.
  • input
    • replacer 함수가 호출된 전체 문자열을 나타냅니다.
// replacement에 대체 함수 지정 예시
const str = 'Hello John Doe, Hello Jane Doe';

function replacer(match, p1, offset, input) {
  console.log('Matched:', match);
  console.log('Group 1:', p1);
  console.log('Start offset:', offset);
  console.log('Input string:', input);

  // 치환된 문자열을 반환
  return 'REPLACED';
}

const newStr = str.replace(/Hello (John|Jane) Doe/g, replacer);
console.log('Result:', newStr);

// 출력 결과
> Matched: Hello John Doe
> Group 1: John
> Start offset: 0
> Input string: Hello John Doe, Hello Jane Doe
> Matched: Hello Jane Doe
> Group 1: Jane
> Start offset: 16
> Input string: Hello John Doe, Hello Jane Doe
> Result: REPLACED, REPLACED

풀이에 적용된 코드

const REG_EXP = /(C|D|F|G|A)#/g

/* 악보에 사용되는 음 중 # 기호가 포함된 음일 경우, 영소문자로 변환 */
const getReplaceMusicNotes = (musicNotes) => {
  return musicNotes.replace(REG_EXP, (_, match) => match.toLowerCase());
}

const mucicNotes = "CC#BCC#BCC#BCC#B";
console.log(getReplaceMusicNotes(mucicNotes)); // CcBCcBCcBCcB

참고

0개의 댓글