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

woolee의 기록보관소·2022년 12월 4일
0

알고리즘 문제풀이

목록 보기
115/178

문제 출처

프로그래머스 lev2 - 방금그곡

나의 풀이

1차시도(66.7/100)

일단 let len = tray.indexOf(tray.find(el => el === m[0])); 이부분이 문제였다. 시작지점과 일치하는 부분이 tray에 여러 개 일수도 있다. indexOf 가장 첫번째만 반환하므로 문제를 일으킨다.

function solution(m, musicinfos) {
  let obj = {};
  m = m.split('');
  for(let i=0; i<m.length; i++) {
    if(m[i]==='#') {
      m[i-1] = m[i-1] + m[i];
      m.splice(i, 1);
    }
  }

  musicinfos.map((v) => {
    v = v.split(",");
    v[0] = v[0].split(":");
    v[1] = v[1].split(":");

    const hh = v[1][0] * 1 - v[0][0] * 1;
    const mm = v[1][1] * 1 - v[0][1] * 1;
    const time = Math.abs(hh) * 60 + Math.abs(mm);
    v[3] = v[3].split("");
    for (let i = 0; i < v[3].length; i++) {
      if (v[3][i] === "#") {
        v[3][i - 1] = v[3][i - 1] + v[3][i];
        v[3].splice(i, 1);
      }
    }
    const mSize = v[3].length;
    // console.log(v, time, mSize);


    let tray = [...v[3]];
    if (time > mSize) {
      let p = 0;
      while (tray.length < time) {
        if (p === mSize - 1) {
          tray.push(v[3][p]);
          p = 0;
        }
        else {
          tray.push(v[3][p]);
          p++;
        }
      }
    } else if (time < mSize) {
      tray = tray.slice(0, time);
    }

    let len = tray.indexOf(tray.find(el => el === m[0]));
    let cpr = tray.slice(len, len+m.length);

    if(cpr.join('') === m.join('')) {
      obj[v[2]] = mSize;
    }
  });

  if (Object.keys(obj).length === 0) return "(None)";
  let max = 0;
  let answer = '';
  for(let x in obj) {
    if(max < obj[x]) {
      max = obj[x];
      answer = x;
    }
  }
  return answer;
}
console.log(
  solution("CC#BCC#BCC#BCC#B", [
    "03:00,03:30,FOO,CC#B",
    "04:00,04:08,BAR,CC#BCC#BCC#B",
  ])
);

2차시도 (86.7/100)

cprBundle 배열을 만들어서 경우의 수를 모두 고려하려고 했다. 그리고 time을 구할 때 시간/분을 나눠서 구하면 문제가 생길 수 있다. 그래서 before과 after로 다시 구한 뒤 time을 재계산했다.

function solution(m, musicinfos) {
  let obj = {};
  m = m.split('');
  for(let i=0; i<m.length; i++) {
    if(m[i]==='#') {
      m[i-1] = m[i-1] + m[i];
      m.splice(i, 1);
    }
  }

  musicinfos.map((v) => {
    v = v.split(",");
    v[0] = v[0].split(":");
    v[1] = v[1].split(":");

    // const hh = v[1][0] * 1 - v[0][0] * 1;
    // const mm = v[1][1] * 1 - v[0][1] * 1;
    // const time = Math.abs(hh) * 60 + Math.abs(mm);
    const before = v[0][0]*60 + v[0][1]*1;
    const after = v[1][0]*60 + v[1][1]*1;
    const time = after - before;
    v[3] = v[3].split("");
    for (let i = 0; i < v[3].length; i++) {
      if (v[3][i] === "#") {
        v[3][i - 1] = v[3][i - 1] + v[3][i];
        v[3].splice(i, 1);
      }
    }
    const mSize = v[3].length;
    console.log(time);

    console.log(v[3], m);


    let tray = [...v[3]];
    if (time > mSize) {
      let p = 0;
      while (tray.length < time) {
        if (p === mSize - 1) {
          tray.push(v[3][p]);
          p = 0;
        }
        else {
          tray.push(v[3][p]);
          p++;
        }
      }
    } else if (time < mSize) {
      tray = tray.slice(0, time);
    }

    let cprBundle = []; 
    let cprTray = [...tray]
    let len = cprTray.indexOf(cprTray.find(el => el === m[0]));
    let cpr = cprTray.slice(len, len+m.length);
    
    while(len>=0) {
      cprBundle.push(cpr);
      len++;

      cprTray = cprTray.slice(len);
      len = cprTray.indexOf(cprTray.find(el => el === m[0]));
      cpr = cprTray.slice(len, len+m.length);
    }
    

    let flag = false;
    for(let i=0; i<cprBundle.length; i++) {
      if(cprBundle[i].join('') === m.join('')) {
        flag = true;
      }
      if(flag) {
        obj[v[2]] = mSize;
        break;
      }
    }
  });

  console.log(obj);

  if (Object.keys(obj).length === 0) return "(None)";
  let max = 0;
  let answer = '';
  for(let x in obj) {
    if(max < obj[x]) {
      max = obj[x];
      answer = x;
    }
  }
  return answer;
}

// console.log(solution("ABC", ["12:00,12:10,HELLO,ABC#ABC#ABC"])); // HELLO
// console.log(solution("ABC", ["12:04,13:00,HELLO,ABC#ABC#ABC"])); // HELLO
// console.log(solution("C#C", ["12:00,12:06,HELLO,C#C#CC#"])); // HELLO
console.log(solution("ABCDEFG", ["11:50,12:04,HELLO,CDEFGAB", "12:57,13:11,BYE,CDEFGAB"])) // HELLO

3차시도 (통과)

악보 길이(mSize)로 비교하는 게 아니라 재생된 시간(time)으로 비교하니 풀렸다. 문제를 제대로 파악하지 못해 삽질을 엄청나게 했다. 삽질한 만큼 코드도 엄청나게 길어졌다...

function solution(m, musicinfos) {
  let obj = {};
  m = m.split('');
  for(let i=0; i<m.length; i++) {
    if(m[i]==='#') {
      m[i-1] = m[i-1] + m[i];
      m.splice(i, 1);
    }
  }

  musicinfos.map((v) => {
    v = v.split(",");
    v[0] = v[0].split(":");
    v[1] = v[1].split(":");

    // const hh = v[1][0] * 1 - v[0][0] * 1;
    // const mm = v[1][1] * 1 - v[0][1] * 1;
    // const time = Math.abs(hh) * 60 + Math.abs(mm);
    const before = v[0][0]*60 + v[0][1]*1;
    const after = v[1][0]*60 + v[1][1]*1;
    const time = after - before;
    v[3] = v[3].split("");
    for (let i = 0; i < v[3].length; i++) {
      if (v[3][i] === "#") {
        v[3][i - 1] = v[3][i - 1] + v[3][i];
        v[3].splice(i, 1);
      }
    }
    const mSize = v[3].length;
    // console.log(time);

    let tray = [...v[3]];
    if (time > mSize) {
      let p = 0;
      while (tray.length < time) {
        if (p === mSize - 1) {
          tray.push(v[3][p]);
          p = 0;
        }
        else {
          tray.push(v[3][p]);
          p++;
        }
      }
    } else if (time < mSize) {
      tray = tray.slice(0, time);
    }

    let cprBundle = []; 
    let cprTray = [...tray]
    let len = cprTray.indexOf(cprTray.find(el => el === m[0]));
    let cpr = cprTray.slice(len, len+m.length);
    
    while(len>=0) {
      cprBundle.push(cpr);
      len++;

      cprTray = cprTray.slice(len);
      len = cprTray.indexOf(cprTray.find(el => el === m[0]));
      cpr = cprTray.slice(len, len+m.length);
    }
    

    let flag = false;
    for(let i=0; i<cprBundle.length; i++) {
      if(cprBundle[i].join('') === m.join('')) {
        flag = true;
      }
      if(flag) {
        // obj[v[2]] = mSize;
        obj[v[2]] = time;
        break;
      }
    }
  });

  if (Object.keys(obj).length === 0) return "(None)";
  let max = 0;
  let answer = '';
  for(let x in obj) {
    if(max < obj[x]) {
      max = obj[x];
      answer = x;
    }
  }
  return answer;
}

// console.log(solution("ABC", ["12:00,12:10,HELLO,ABC#ABC#ABC"])); // HELLO
// console.log(solution("ABC", ["12:04,13:00,HELLO,ABC#ABC#ABC"])); // HELLO
// console.log(solution("C#C", ["12:00,12:06,HELLO,C#C#CC#"])); // HELLO
console.log(solution("ABCDEFG", ["11:50,12:04,HELLO,CDEFGAB", "12:57,13:11,BYE,CDEFGAB"])) // HELLO

다른 풀이

엄청나다

const solution = (m, musicInfos) => {
  let answer = '';

  musicInfos = musicInfos.map(e => {
      let eArr = e.split(',');
      // console.log(eArr);
      let timeDiff = (new Date(`1970-01-01 ${eArr[1]}:00`) - new Date(`1970-01-01 ${eArr[0]}:00`)) / 60000;
      let melody = eArr[3].replace(/[A-Z]#/g,m => m[0].toLowerCase());
      // console.log(melody);
      melody = melody.repeat(Math.ceil(timeDiff / melody.length)).substr(0, timeDiff);
      // console.log(melody);
      return `${timeDiff},${eArr[2]},${melody}`;
  });

  musicInfos.sort((a,b) => b.split(',')[0] - a.split(',')[0]);

  answer = musicInfos.filter(e => e.split(',')[2].indexOf(m.replace(/[A-Z]#/g,m => m[0].toLowerCase())) != -1);

  return answer.length == 0 ? '(None)' : answer[0].split(',')[1];
}

// console.log(solution("ABC", ["12:00,12:10,HELLO,ABC#ABC#ABC"])); // HELLO
// console.log(solution("ABC", ["12:04,13:00,HELLO,ABC#ABC#ABC"])); // HELLO
console.log(solution("C#C", ["12:00,12:06,HELLO,C#C#CC#"])); // HELLO
// console.log(solution("ABCDEFG", ["11:50,12:04,HELLO,CDEFGAB", "12:57,13:11,BYE,CDEFGAB"])) // HELLO

내 풀이와 비교해보자면,

// 1. 내가 아래와 같이 시간차이를 구했다면,

      v = v.split(",");
      v[0] = v[0].split(":");
      v[1] = v[1].split(":");
  
      const before = v[0][0]*60 + v[0][1]*1;
      const after = v[1][0]*60 + v[1][1]*1;
      const time = after - before;

위 풀이는 아래와 같이 한 줄로 풀어냈다.

let timeDiff = (new Date(`1970-01-01 ${eArr[1]}:00`) - new Date(`1970-01-01 ${eArr[0]}:00`)) / 60000;

// 2. #이 붙은 애들을 비교하기 위해 나는 아래와 같이 구했다면,

let obj = {};
m = m.split('');
for(let i=0; i<m.length; i++) {
  if(m[i]==='#') {
    m[i-1] = m[i-1] + m[i];
    m.splice(i, 1);
  }
}

musicinfos.map((v) => {
  v = v.split(",");
  v[3] = v[3].split("");
  for (let i = 0; i < v[3].length; i++) {
    if (v[3][i] === "#") {
      v[3][i - 1] = v[3][i - 1] + v[3][i];
      v[3].splice(i, 1);
    }
  }
  const mSize = v[3].length;
}

위 풀이에서는 아래와 같이 한줄로 풀어냈다. #을 하나하나 구분하는게 아니라 #이 붙은 애들은 소문자로 변환해 구분할 수 있게.

let melody = eArr[3].replace(/[A-Z]#/g,m => m[0].toLowerCase());

// 3. 멜로디를 구하기 위해 나는 아래와 같이 구했다면,

const mSize = v[3].length;
  
      let tray = [...v[3]];
      if (time > mSize) {
        let p = 0;
        while (tray.length < time) {
          if (p === mSize - 1) {
            tray.push(v[3][p]);
            p = 0;
          }
          else {
            tray.push(v[3][p]);
            p++;
          }
        }
      } else if (time < mSize) {
        tray = tray.slice(0, time);
      }

위 풀이는 이렇게 한줄로 풀어냈다. repeat은 반복횟수를 매개변수로 받는다.

melody = melody.repeat(Math.ceil(timeDiff / melody.length)).substr(0, timeDiff);

// 4. 일치하는지 찾기 위해 나는 아래와 같이 풀었다면,

let cprBundle = []; 
      let cprTray = [...tray]
      let len = cprTray.indexOf(cprTray.find(el => el === m[0]));
      let cpr = cprTray.slice(len, len+m.length);
      
      while(len>=0) {
        cprBundle.push(cpr);
        len++;
  
        cprTray = cprTray.slice(len);
        len = cprTray.indexOf(cprTray.find(el => el === m[0]));
        cpr = cprTray.slice(len, len+m.length);
      }
      
  
      let flag = false;
      for(let i=0; i<cprBundle.length; i++) {
        if(cprBundle[i].join('') === m.join('')) {
          flag = true;
        }
        if(flag) {
          // obj[v[2]] = mSize;
          obj[v[2]] = time;
          break;
        }
      }
    });
  
    if (Object.keys(obj).length === 0) return "(None)";
    let max = 0;
    let answer = '';
    for(let x in obj) {
      if(max < obj[x]) {
        max = obj[x];
        answer = x;
      }
    }
    return answer;
  }

위 풀이는 이렇게 찾아냈다. 그리고 위 풀이처럼 musicInfos에서 map을 돌고 나서 return으로 musicInfos에 값을 저장하는 게 효율적인 것 같다.
arr = arr.map(el => return 연산결과);

musicInfos.sort((a,b) => b.split(',')[0] - a.split(',')[0]);

  answer = musicInfos.filter(e => e.split(',')[2].indexOf(m.replace(/[A-Z]#/g,m => m[0].toLowerCase())) != -1);

  return answer.length == 0 ? '(None)' : answer[0].split(',')[1];
profile
https://medium.com/@wooleejaan

0개의 댓글