두 문자열 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 함수를 완성해주세요.
s | skip | index | result |
---|---|---|---|
"aukks" | "wbqd" | 5 | "happy" |
문자열 a부터 z까지 담긴 배열을 만들고 그 원소가 skip에 해당하지 않는 문자열만 골라서 변수에 저장한다.
이중 for 문을 돌려서 s[i]의 문자와 1번의 배열[j]의 문자가 같으면 j+index를 새로운 idx 변수에 담아준다.
1번 배열의 원소 중 2번의 idx와 1번의 배열 길이를 나눈 나머지 값을 answer에 더한다.
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;
}
문자열 a부터 z까지 담긴 배열을 만들고 그 원소가 skip에 해당하지 않는 문자열만 골라서 변수에 저장한다.
s를 배열로 만든 후 map을 돌려 1번의 배열에서 s의 원소값의 index와 매개변수로 받은 index를 더하고 1번 배열의 길이만큼 나눈 뒤 나머지 값으로 1번 배열의 원소를 추출한다.
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문 말고 자바스크립트에서 제공해주는 내장 함수에 대해 공부할 필요가 있다고 느낀다. 객체 지향 프로그래밍과 함수형 프로그래밍을 비교했을 때 지금 상황에서는 함수형 프로그래밍의 방법을 채택하는 것이 맞다고 생각한다.
또한 프로그래머스에서 기본적으로 제공해주는 테스트 케이스말고 다른 테스트 케이스도 잘 생각해서 문제를 풀어야겠다.