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

한재창·2023년 6월 12일
0

둘만의 암호

문제 설명

두 문자열 s와 skip, 그리고 자연수 index가 주어질 때, 다음 규칙에 따라 문자열을 만들려 합니다. 암호의 규칙은 다음과 같습니다.

문자열 s의 각 알파벳을 index만큼 뒤의 알파벳으로 바꿔줍니다.
index만큼의 뒤의 알파벳이 z를 넘어갈 경우 다시 a로 돌아갑니다.
skip에 있는 알파벳은 제외하고 건너뜁니다.
예를 들어 s = "aukks", skip = "wbqd", index = 5일 때, a에서 5만큼 뒤에 있는 알파벳은 f지만 [b, c, d, e, f]에서 'b'와 'd'는 skip에 포함되므로 세지 않습니다. 따라서 'b', 'd'를 제외하고 'a'에서 5만큼 뒤에 있는 알파벳은 [c, e, f, g, h] 순서에 의해 'h'가 됩니다. 나머지 "ukks" 또한 위 규칙대로 바꾸면 "appy"가 되며 결과는 "happy"가 됩니다.

두 문자열 s와 skip, 그리고 자연수 index가 매개변수로 주어질 때 위 규칙대로 s를 변환한 결과를 return하도록 solution 함수를 완성해주세요.

제한사항

  • 5 ≤ s의 길이 ≤ 50
  • 1 ≤ skip의 길이 ≤ 10
  • s와 skip은 알파벳 소문자로만 이루어져 있습니다.
    • skip에 포함되는 알파벳은 s에 포함되지 않습니다.
  • 1 ≤ index ≤ 20

입출력 예

sskipindexresult
"aukks""wbqd"5"happy"

입출력 예 설명

  • 입출력 예 #1
    • 본문 내용과 일치합니다.

나의 풀이

  1. 문자열 a부터 z까지 담긴 배열을 만들고 그 원소가 skip에 해당하지 않는 문자열만 골라서 변수에 저장한다.

  2. 이중 for 문을 돌려서 s[i]의 문자와 1번의 배열[j]의 문자가 같으면 j+index를 새로운 idx 변수에 담아준다.

  3. 1번 배열의 원소 중 2번의 idx와 1번의 배열 길이를 나눈 나머지 값을 answer에 더한다.

  4. answer를 return 한다.

function solution(s, skip, index) {
    var answer = '';

    const alphabet = new Array(26).fill().map((_, i) => String.fromCharCode(i + 97)).filter(str => !skip.includes(str));
    
    for(let i=0; i<s.length; i++) {
        for(let j=0; j<alphabet.length; j++) {
            if(s[i] === alphabet[j]) {
                const idx = j+index;
                answer += alphabet[idx % alphabet.length];
            }
        }
    }

    return answer;
}

내가 좋다고 생각한 풀이

  1. 문자열 a부터 z까지 담긴 배열을 만들고 그 원소가 skip에 해당하지 않는 문자열만 골라서 변수에 저장한다.

  2. s를 배열로 만든 후 map을 돌려 1번의 배열에서 s의 원소값의 index와 매개변수로 받은 index를 더하고 1번 배열의 길이만큼 나눈 뒤 나머지 값으로 1번 배열의 원소를 추출한다.

  3. join() 메서드를 사용해서 추출한 문자를 return 한다.

function solution(s, skip, index) {
    const alphabet = ["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"].filter(c => !skip.includes(c));
    return s.split("").map(c => alphabet[(alphabet.indexOf(c) + index) % alphabet.length]).join("");
}

배운점

나는 이 부분을 맨 처음에 아래와 같이 코드를 작성해서 테스트 케이스 4개를 틀렸었다. 결국 틀린 이유를 찾지 못하고 나머지로 정답을 구했다.

 if(s[i] === alphabet[j]) {
     const idx = j+index;
     answer += idx < alphabet.length ? alphabet[idx] : alphabet[idx - alphabet.length];
}

나와 같이 틀린 사람들이 많아서 댓글을 읽어보니 다음과 같은 상황에서 위의 코드는 오류를 일으킨다.

알파벳 개수는 26개고, skip에는 최대 10개의 알파벳이 들어갈 수 있습니다. 따라서 alphabet.length의 하한은 16입니다.
index <= 20이므로, 다음과 같은 상황을 고려해봅시다.

skip = 'abcdefghij' 일 때, s에 z가 포함되고 index = 20인 경우.

이 경우 alpha에는 k~z(16개)의 문자가 있는데, alphabet.index('z') = 15이고 index = 20이므로 new_idx는 35가 됩니다. 여기에서 new_idx - alphabet.length를 빼면 20이 되므로, alphabet의 범위를 넘어가버립니다.

느낀점

for문 말고 자바스크립트에서 제공해주는 내장 함수에 대해 공부할 필요가 있다고 느낀다. 객체 지향 프로그래밍과 함수형 프로그래밍을 비교했을 때 지금 상황에서는 함수형 프로그래밍의 방법을 채택하는 것이 맞다고 생각한다.
또한 프로그래머스에서 기본적으로 제공해주는 테스트 케이스말고 다른 테스트 케이스도 잘 생각해서 문제를 풀어야겠다.

profile
취준 개발자

0개의 댓글