프로그래머스 js 방금그곡

이명진·2022년 5월 11일
0

코드카타

목록 보기
25/68

2018년도 카카오 블라인드 채용 문제이다.

문제 설명

방금 그곡 서비스는 방금 들었던 곡을 알려준다.
네오는 절대음감인지 기가막히게 노래의 멜로디를 들으면 음을 알수 있고 음을 기억한다.
방금그곡 서비스에서는 배열로 음악제목, 재상이 시작되고 끝난시간, 악보를 제공한다.
네오는 들었던 멜로디로 노래를 찾으려고 한다. 방금그곡 서비스의 악보를 비교하여 맞는 악보 제목을 리턴하면 되는 문제이다.

단 조건이 있다. 멜로디는 1개당 1분이다. 맞는게 없다면 'None'을 리턴하면 된다.
그리고 조건이 일치하는 음악이 여러 개일 때에는 라디오에서 재생된 시간이 제일 긴 음악 제목을 반환한다. 재생된 시간도 같을 경우 먼저 입력된 음악 제목을 반환한다.

복잡할까 싶었는데 풀만한 문제였다. 역시 2018년도 문제는 풀수 있을듯 싶다.

첫번째 시도

function solution(m, musicinfos) {
    let answer = '';
  	let same = [];
  	musicinfos.map(x=>{
      let [sTime,eTime,title,score] = x.split(',')
      if(score.length<=m.length){
        while(score.length<=m.length){
          score+=score
        }
      }
      if(score.includes(m)){
       
        let time = calTime(sTime,eTime)
     
        same.push([time,title])
        
      }
    })

  	if(same.length>1){
      let time = same.map(x=>{
        return x[0]
      })
      let max = Math.max.apply(null,time)
      let idx = time.findIndex(x=>{return x===max})
      return same[idx][1]
    }else if(!same.length){
      return '(None)';
    }else{
      return same[0][1]
    }
  
}
function calTime(_s,_e){
  let [sH,sM] = _s.split(':')
  let [eH,eM] = _e.split(':')
  let calTimeH = Number(eH)-Number(sH);
  let calTimeM = Number(eM)>Number(sM)?Number(eM)-Number(sM):(Number(eM)+60)-Number(sM);
  return Number(eM)>Number(sM)?calTimeH*60+calTimeM : (calTimeH-1)*60+calTimeM
}

조건에 일치하는 음악이 여러개일 경우 시간이 긴 음악 제목을 반환 해야 하기 때문에 calTime 함수를 만들어서 소요 시간을 구했다.
처음 시도 때 테케도 다맞고 제출하기 눌렀을때 3문제를 틀려서 쉽게 해결할수 있을거라고 생각했다. 왜틀렸을까 생각해보다가 질문하기에서 힌트를 얻게 되었다.
처음에 로직을 짰을때 네오가 기억한 멜로디보다 악보가 적으면 멜로디보다 많게 악보를 계속 붙여주었는데. 여기서 오류가 있었다.
조건중에 악보 한개당 1분 이란 조건이 괜히 있는게 아니었다.
만약 시간이 짧은데 악보가 긴경우에는 악보를 잘라야 했다.

그래서 로직을 수정하기로 했다.
calTime 함수를 활용하여 그만큼의 악보를 잘라주고 붙여주는 것이었다.
다행히도 calTime함수를 만들어 놔서 조금만 수정할수 있었다.

두번째 시도

function solution(m, musicinfos) {
    let answer = '';
  	let same = [];
  	musicinfos.map(x=>{
      let [sTime,eTime,title,score] = x.split(',')
      let playTime = calTime(sTime,eTime)
      let totalScore = '';
      for(let i=0; i<playTime;i++){
      // console.log(score.length,i)
      if(i>=score.length){
         let letter = i%score.length
         totalScore += score[letter]
        
        }else{
          totalScore += score[i]
        }
      }

      console.log(totalScore.includes(m))
      if(totalScore.includes(m)){
       
    
        same.push([playTime,title])
        
      }
    })
  console.log(same)
  	if(same.length>1){
      let time = same.map(x=>{
        return x[0]
      })
      let max = Math.max.apply(null,time)
      let idx = time.findIndex(x=>{return x===max})
      return same[idx][1]
    }else if(!same.length){
      return '(None)';
    }else{
      return same[0][1]
    }
  
}
function calTime(_s,_e){
  let [sH,sM] = _s.split(':')
  let [eH,eM] = _e.split(':')
  let calTimeH = Number(eH)-Number(sH);
  let calTimeM = Number(eM)>Number(sM)?Number(eM)-Number(sM):(Number(eM)+60)-Number(sM);
  return Number(eM)>Number(sM)?calTimeH*60+calTimeM : (calTimeH-1)*60+calTimeM
}

나온 시간만큼 악보를 잘라주고 붙여주었다.
로직을 수정하고 통과할거라고 생각하며 테스트 케이스 를 돌렸는데
마지막 문제에서 틀렸다. 테스트 케이스 3번 에서는 악보에 (#) 이 들어있는 경우였다. 샾을 전혀 생각하지 못했다.. 고민 고민을 하다가
악보에 #이 붙어 있는 경우 전혀 상관없는 ZYXWV 로 치환작업을 해주었다.

세번째 도전

function solution(m, musicinfos) {
    let answer = '';
  	let same = [];
  	musicinfos.map(x=>{
      let [sTime,eTime,title,score] = x.split(',')
      let playTime = calTime(sTime,eTime)
      let totalScore = '';
      score = changeScore(score);
        m = changeScore(m)
      for(let i=0; i<playTime;i++){
   
      if(i>=score.length){
         let letter = i%score.length 
         totalScore += score[letter]
        
        }else{
          totalScore += score[i]
        }
      }

     
      if(totalScore.includes(m)){
       
    
        same.push([playTime,title])
        
      }
    })
 
  	if(same.length>1){
      let time = same.map(x=>{
        return x[0]
      })
      let max = Math.max.apply(null,time)
      let idx = time.findIndex(x=>{return x===max})
      return same[idx][1]
    }else if(!same.length){
      return '(None)';
    }else{
      return same[0][1]
    }
  
}
function calTime(_s,_e){
  let [sH,sM] = _s.split(':')
  let [eH,eM] = _e.split(':')
  let calTimeH = Number(eH)-Number(sH);
  let calTimeM = Number(eM)>Number(sM)?Number(eM)-Number(sM):(Number(eM)+60)-Number(sM);
  return Number(eM)>Number(sM)?calTimeH*60+calTimeM : (calTimeH-1)*60+calTimeM
}
function changeScore(_score){
  if(!_score.includes('#')){
    return _score
  }else{
    let newScore = [];
  	_score.split('').map(x=>{
      if(x!=='#'){
        newScore.push(x)
      }else{
        let prv = newScore.pop();
        prv+='#'
        if(prv === 'C#'){
          newScore.push('z')
        }else if(prv === 'D#'){
          newScore.push('y')
        }else if(prv === 'F#'){
           newScore.push('x')
        }else if(prv === 'G#'){
           newScore.push('w')
        }else {
           newScore.push('v')
        }
      }
    })
    return newScore.join('')
  }
}

changeScore 함수를 만들어서 조건에 맞춰서 문자를 변환해주었다.
로직이 지저분한것 같지만.. 나중에 리팩토링 하기로 생각하며 테스트와 채점을 돌렸다. 결과는 통과!
통과할수 있었다. 다른 사람들의 코드를 보면서 리팩토링 에 참고하여 코드를 줄여보는 것에 힘써야 할것 같다.

리팩토링

다른 사람의 풀이를 보니 굳이 샵 부분을 다른 언어로 치환하지 않아도 됨을 알게 되었다.
그냥 소문자로 변경해도 되는 문제였다.

function changeScore(_score){
  if(!_score.includes('#')){
    return _score
  }else{
    let newScore = [];
  	_score.split('').map(x=>{
      if(x!=='#'){
        newScore.push(x)
      }else{
        let prv = newScore.pop();
        prv = prv.toLowerCase()
         newScore.push( prv)
      }
    })
    return newScore.join('')
  }
}

길었던 if문 조건을 세줄로 줄일수가 있었다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글