ericagong / algorithm_solving

2 stars 0 forks source link

[구현] 방금 그 곡 #74

Closed ericagong closed 1 year ago

ericagong commented 1 year ago

⭐ 성찰

  1. A#을 a로 치환해 A와 A# 구분. (길이를 유지해야하기 때문에 해당 방식 사용) ㄴ String.prototype.replace

  2. 문자열 반복 및 자르기에 각각 String.prototype.repeat(횟수), String.prototype.slice(startIdx, endIdx) 사용

  3. cf) 배열 반복 및 자르기에 각각 Array.prototype.concat()을 반복 처리, Array.prototype.slice(startIdx, endIdx) 사용

  4. 시간 구하는 함수: (new Date() - new Date(1995-10-31 08:00:00)) / 60000 형태로 간단히 계산 가능

❓ 문제 상황

방금 그 곡

👨‍💻 문제 해결

✅ 1차 풀이: replaceAll을 이용한 치환

  1. ⭐ 멜로디에서 /[ABCDEF]#/ 형태의 패턴이 있다면 소문자로 치환해 /[ABCDEF]#/을 한 글자로 표현.
  2. 모든 곡에 대해 재생 시간 계산
  3. 재생 시간이 악보 길이보다 길다면, 악보를 재생시간만큼 반복. 짧거나 같다면 악보를 slice 처리.
  4. 재생시간에 따라 조정된 악보에 해당 멜로디가 들어있는지 확인하여, 들어있다면 후보군에 [노래이름, 재생시간] 형태로 추가.
  5. 후보군이 없으면 (None) 반환. 있으면 재생 시간에 따라 내림차순 정렬해 첫 요소의 노래 이름 반환.

function getPlayTime(start, end) { const [sHH, sMM] = start.split(":").map(Number); const [eHH, eMM] = end.split(":").map(Number); return eHH 60 + eMM - (sHH 60 + sMM) + 1; // 종료 시간까지 포함 }

// 치환 함수 - 빼먹지 않도록 주의 function getNotes(info) { return info .replaceAll("A#", "a") .replaceAll("C#", "c") .replaceAll("D#", "d") .replaceAll("F#", "f") .replaceAll("G#", "g"); }

function solution(m, musicinfos) { m = getNotes(m);

const candidates = []; musicinfos.forEach((info) => { const [start, end, name, note] = info.split(","); const playTime = getPlayTime(start, end); let playNotes = getNotes(note);

if (playNotes.length >= playTime) {
  playNotes = playNotes.slice(0, playTime);
} else {
  const q = parseInt(playTime / playNotes.length);
  const r = playTime % playNotes.length;
  playNotes = playNotes.repeat(q) + playNotes.slice(0, r);
}

if (playNotes.includes(m)) candidates.push([name, playTime]);

});

if (candidates.length === 0) return "(None)"; // 재생 시간 내림차순 정렬 else return candidates.sort((a, b) => b[1] - a[1])[0][0]; }


### ✅ 2차 풀이: 특정 함수 개선
1. 재생 시간 구하는 함수: 직접 계산 -> Date 빌트인 객체 사용해 계산
2. 재생 시간에 따라 조정된 악보 구하기 -> Math 빌트인 객체 사용해 개선
```javascript

function solution(m, musicinfos) {
  m = m.replace(/[A-Z]#/g, (v) => v[0].toLowerCase());;

  const candidates = [];
  musicinfos.forEach((info) => {
    const [start, end, name, note] = info.split(",");
    const playTime =
      (new Date(`1970-01-01 ${end}:00`) - new Date(`1970-01-01 ${start}:00`)) / 60000;
    let playNotes = note.replace(/[A-Z]#/g, v => v[0].toLowerCase()); // 함수 형태로 작성 가능

    playNotes = playNotes.repeat(Math.ceil(playTime / playNotes.length)).slice(0, playTime)

    if (playNotes.includes(m)) candidates.push([name, playTime]);
  });

  if (candidates.length === 0) return "(None)";
  // 재생 시간 내림차순 정렬
  else return candidates.sort((a, b) => b[1] - a[1])[0][0];
}

✅ 3차 풀이: 특정 함수 개선

function getPlayTime(start, end) {
    const [sh, sm] = start.split(':').map(Number)
    const [eh, em] = end.split(':').map(Number)
    const startTime = sh * 60 + sm
    const endTime = eh * 60 + em
    return endTime - startTime 
}

function getMelody(notes, playTime) {
    let melody = changeNote(notes)

    melody = melody.repeat(Math.ceil(playTime / melody.length))
    melody = Array.from(melody).slice(0, playTime).join('')

    return melody
}

function changeNote(notes) {
    const noteG = /[A-G]#?/gi

    const tempNotes = notes.match(noteG)
    let melody = ''
    tempNotes.forEach((note) => {
        if(note.includes('#')) melody += note.replace('#', '').toLowerCase()
        else melody += note
    })

    return melody
}

function solution(m, musicinfos) {
    let musics = []
    musicinfos.forEach((info) => {
        const [start, end, title, notes] = info.split(',')
        const playTime = getPlayTime(start, end)
        const melody = getMelody(notes, playTime)
        musics.push([title, melody, playTime])
    })

    const target = changeNote(m)
    musics = musics.filter((music) => music[1].includes(target)) 

    if(musics.length === 0) return '(None)'

    const musicTitle = musics.sort((a, b) => {
        if(a[2] !== b[2]) return b[2] - a[2]
    })[0][0]

    return musicTitle

}
ericagong commented 1 year ago

✅ 2차 풀이 반영 완료