[프로그래머스 lev2/JS] 압축

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

알고리즘 문제풀이

목록 보기
43/178

문제 출처

프로그래머스 lev2 - 압축

문제

나의 풀이

1차 시도 (65.0 / 100)

function solution(msg) {
  let answer = [];
  let idx = { 
    'A':1, 'B':2, 'C':3, 'D':4, 'E':5, 'F':6, 'G':7, 'H':8, 
    'I':9, 'J':10, 'K':11, 'L':12, 'M':13, 'N':14, 'O':15, 
    'P':16, 'Q':17, 'R':18, 'S':19, 'T':20, 'U':21, 'V':22, 
    'W':23, 'X':24, 'Y':25, 'Z':26,
  }
  let idxCnt=27;
  let pc=0;
  while (pc!==msg.length-1) {
    // console.log(pc);
    let cnt=pc+1;
    while (idx[msg.slice(pc, cnt)]) {
      if (cnt === msg.length) break;
      cnt++;
    }
    if (cnt === msg.length && idx[msg.slice(pc, cnt)]) {
      answer.push(idx[msg.slice(pc, cnt)]);
    }
    else {
      answer.push(idx[msg.slice(pc, cnt-1)]);
      idx[msg.slice(pc, cnt)]=idxCnt;
      idxCnt++;
    }
    if (cnt>=2) {
      pc=cnt-1;
    }
    else pc++;
  }
  // console.log(idx);
  return answer;
}
console.log(solution("KAKAO"));
// console.log(solution("TOBEORNOTTOBEORTOBEORNOT"));
// console.log(solution("ABABABABABABABAB"));

2차 시도 (통과코드)

  1. 알파벳 색인을 key-value 형태로 생성한 후,

  2. while 문을 순회한다.
    msg.slice(pc, cnt)를 한번 더 순회하는데, cnt를 계속 ++해주다가,
    idx에 없는 경우가 생기면 그때서야 idx에 값을 생성해주고 그 이전 값을 answer에 넣어준다.

첫번째 시도에서 틀린 이유는, 마지막 부분 처리였다.
tc 2,3,4의 경우와 달리 tc 1에서는 pc가 msg.length-1을 한번 더 순회해야 한다.
=> 단순히 (pc!==msg.length-1) 일때는 cnt==msg.length일 때 break;를 해주지 않아도 while 문이 종료되지만,
=> (pc===msg.length) 일때는 cnt==msg.length일 때 break;해주지 않으면 무한 루프에 빠진다.
예를 들어, tc1에서 pc=4,cnt=5일 때 break해주지 않으면 계속 (pc,cnt) 가(4,5)로 무한 루프에 빠진다.
function solution(msg) {
  let answer = [];
  // 1.
  let idx = { 
    'A':1, 'B':2, 'C':3, 'D':4, 'E':5, 'F':6, 'G':7, 'H':8, 
    'I':9, 'J':10, 'K':11, 'L':12, 'M':13, 'N':14, 'O':15, 
    'P':16, 'Q':17, 'R':18, 'S':19, 'T':20, 'U':21, 'V':22, 
    'W':23, 'X':24, 'Y':25, 'Z':26,
  }
  let idxCnt=27;
  let pc=0;
  let cnt=0;
  // 2.
  while (pc!==msg.length) {
    cnt=pc+1;
    console.log(pc, cnt);
    while (idx[msg.slice(pc, cnt)]) {
      if (cnt >= msg.length) break;
      cnt++;
    }
    console.log(pc, cnt);
    if (cnt >= msg.length && idx[msg.slice(pc, cnt)]) {
      answer.push(idx[msg.slice(pc, cnt)]);
      break;
    }
    else {
      answer.push(idx[msg.slice(pc, cnt-1)]);
      idx[msg.slice(pc, cnt)]=idxCnt;
      idxCnt++;
    }
    pc=cnt-1; 
  }
  // console.log(idx);
  return answer;
}
// console.log(solution("KAKAO"));
// console.log(solution("TOBEORNOTTOBEORTOBEORNOT"));
console.log(solution("ABABABABABABABAB"));

다른 풀이

알파벳으로 배열을 먼저 생성한 뒤, reduce를 통해 객체를 생성하기

function solution(msg) {
  var list = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
  var dic = list.reduce((d, a, i) => (d[a] = i + 1, d), {})

  var result = [];

  var maxLen = 1;
  for (var i = 0; i < msg.length; i++) {

      var w = msg[i];
      var c = msg[i+1];
      while (dic[w+c] && i < msg.length - 1) {
          i++;

          w = w+c;
          c = msg[i+1];
      }

      result.push(dic[w]);

      list.push(dic[w+c]);
      dic[w+c] = list.length;
  }

  return result;
}

// console.log(solution("KAKAO"));
// console.log(solution("TOBEORNOTTOBEORTOBEORNOT"));
console.log(solution("ABABABABABABABAB"));

배열 요소에 keys() 메서드를 사용하면 index 값을 얻을 수 있다.
[...Array(26).keys()]를 사용하면 각 index 값으로 이루어진 26개 요소를 갖는 배열을 만들어낼 수 있다.
String.fromCharCode()를 사용하면 숫자로부터 유니코드 문자열을 얻어낼 수 있다. 유니코드 0~127 숫자는 아스키코드와 동일한 의미를 가진다.

  • 대문자 A ~ 대문자 Z : 65~90
  • 소문자 a ~ 소문자 z : 97~122
  • 숫자 0 ~ 숫자 9 : 48~57
function solution(msg) {
    let answer = [],
        dictionary = [''].concat([...Array(26).keys()].map(v => String.fromCharCode(v + 65)));

    while (msg.length) {
        for (let i = dictionary.length - 1; i >= 0; i--) {
            let characters = dictionary[i];

            if (new RegExp('^' + characters).test(msg)) {
                let newCharacter = msg.substr(0, characters.length + 1);

                if (dictionary.indexOf(newCharacter) < 0) dictionary.push(newCharacter);

                msg = msg.substr(characters.length);
                answer.push(i);
                break;
            }
        }
    }

    return answer;
}
profile
https://medium.com/@wooleejaan

0개의 댓글