본문 바로가기
알고리즘

[프로그래머스]둘만의 암호

by limew 2023. 5. 27.

https://school.programmers.co.kr/learn/courses/30/lessons/155652

 

<1 번째>

  1. 알파벳 a에서 z까지 어떻게 구현하지? => 생각이 난건 array, string
  2. s를 돌면서 현재 문자의 인덱스 구하기
  3. 정해진 이동수 만큼 현재 문자에서 이동하기 (단 여기서 당시의 문자가 skip해야하면 이동수--) 
  4. 다 이동하고 난뒤의 문자를 answer에 추가
function solution(s, skip, index) {
  var answer = "";
  const alphabets = "abcdefghijklmnopqrstuvwxyz";

  for (let i = 0; i < s.length; i++) {
    const curr = s[i];
    let currIndex = [...alphabets].findIndex((a) => a === curr);
    let next;

    // 횟수만큼
    for (let j = 0; j < index; j++) {
      const nextIndex = (currIndex + 1) % alphabets.length; //
      next = alphabets[nextIndex];
      // skip
      if (skip.includes(next)) {
        j--;
      }
      // 다음 알파벳으로 이동
      currIndex += 1;
    }
    answer += next;
  }
  return answer;
}

근데 위에서 처럼 굳이 하나씩 스킵할 필요가 없었다.. 이유는 밑에


<2 번째>

  1. skip을 처음에 미리 다 제외하고 난 뒤 index만큼 이동
  2. 이동한 뒤 범위를 초과하는걸 방지하기 위해  % 필터링 된 알파벳들 개수
  • n + "" :  숫자 => string
  • [...string].filter()
function solution(s, skip, index) {
    var answer = '';
    const alphabets = "abcdefghijklmnopqrstuvwxyz";
    const filteredAlphabets = [...alphabets].filter(a => !skip.includes(a));
    
    [...s].forEach(currS => {
        const currIndex = filteredAlphabets.findIndex(a => a === currS);
        const next = filteredAlphabets[(currIndex + index) % filteredAlphabets.length];
        answer += next;
    })
    return answer;
}

하지만 위의 방법도 여전히 알파벳 문자열이 찝찝하고 [...alphabets].filter, findIndex 가 신경쓰인다.

찾아보니 includes, fiilter 메서드들이 for보다 70%느리다고 한다.


<3 번째>

핵심 뽀인트

  • 알파벳을 문자열에서 말고 ASCII 에서 가져오기 (소문자 a~z: 97~122)
  • char과 아스키코드의 변환
    • str.charCodeAt(i):  str에서 i번째 char을 => code로 변환
    • String.fromCharCode(code): code => char
  • Set으로 skip해야되는 code들 미리 구해놓기
    • object, set의 차이점?
      object은 key, value 두개를 저장하지만, set은 value자체가 key이다.
  • %처리하기
    • 0에서 시작하는게 아니라 헷갈리지만
      1. 값을 빼줘서 0에서 시작하게 바꾼뒤
      2. % 처리하고
      3. 다시 처음에 뺸 값을 더해주면 된다
    • 예) 97~122 => 0~25 => %26 => +97
    • ((현재 수 + 이동스텝) - aCharCode) % alphaLength + aCharCode
function solution(s, skip, index) {
    var answer = '';
    const aCharCode = "a".charCodeAt();
    const alphaLength = "z".charCodeAt() - aCharCode + 1;
    const skipCharCodes = new Set();
    
    for (const c of skip) {
        skipCharCodes.add(c.charCodeAt());
    }
    
    for (let i = 0; i < s.length; i++) {
        let currCharCode = s.charCodeAt(i); // s의 i번째의 char을 code로 변환
        let endCharCode;
        let shift = 0;
        
        while (shift < index) {
            endCharCode = ((currCharCode + 1) - aCharCode) % alphaLength + aCharCode;
            if (!skipCharCodes.has(endCharCode)) {
                shift++;
            }
            currCharCode++;
        }
        answer += String.fromCharCode(endCharCode); // code => char
    }
    return answer;
}