문제 설명
두 문자열 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
입출력 예
s | skip | index | result |
"aukks" | "wbqd" | 5 | "happy" |
풀이
const alphabet = "abcdefghijklmnopqrstuvwxyz";
const solution = (s, skip, index) =>
[...s].reduce((result, cur, idx, arr) => {
const curPosition = alphabet.indexOf(cur);
let count = 0;
let stepCount = 0;
while(stepCount < index){
count ++;
if(skip.includes(alphabet[(curPosition + count) % alphabet.length])) continue;
stepCount += 1;
}
result[idx] = alphabet[(curPosition + count) % alphabet.length];
return result;
}, [...s]).join("");
우선 알파벳을 상수로 지정해두고,
s를 배열로 변환 후, reduce()로 각 문자마다 처리를 해주었다.
현재 문자의 알파벳 순서를 curPosition에 할당 하고,
넘어가는 숫자와 실제 넘어간 숫자를 count와 stepCount에 0으로 초기화 했다.
그다음 실제 넘어간 숫자인 stepCount가 주어진 index와 같아질때까지 while문으로
매번 count를 1 증가시키고, curPosition + count 번째의 알파벳이 skip배열에 존재하는지 includes()로 확인 후,
존재하면 continue, 존재하지 않음녀 stepCount도 1 증가시켜 준다.
while문이 종료되면, 결과 배열의 idx번째 원소를 알파벳의 curPosition + count 로 변경해주어야 하는데,
이때 curPosition + count를 알파뱃의 갯수만큼 나눈 나머지를 넣어 줘야 z 이후에 다시 a로 돌아올 수 있다.
예를들어 x에서 5만큼 가야 한다고 하면,
alpabet[24] alpabet[25] alpabet[26] alpabet[27] alpabet[28] :
즉, "y" "z" undefined undefined undefined 가 될것이다.
여기서 항상 배열의 갯수로 나눠주면
alpabet[24 % 26] alpabet[25 % 26] alpabet[26 % 26] alpabet[27 % 26] alpabet[28 % 26] :
alpabet[24] alpabet[25] alpabet[0] alpabet[1] alpabet[2] :
즉, "y" "z" "a" "b" "c" 가 된다.
특정 횟수만큼 배열을 순회할때 유용하다.
마지막으로 join("")으로 문자열로 변경 후 리턴해준다.
다른 풀이
요즘 reduce에 너무 꽂혀서 그냥 대충 보고 냅다 reduce로 풀어버리는데
대부분의 다른 풀이는 기존 alpabet 배열에서 skip에 들어있는 원소들을 제외 시킨 다음
map으로 깔끔하게 풀어낸 부분이 많았다.
호.. 어떻게 저런생각을했지..
const alphabet = "abcdefghijklmnopqrstuvwxyz";
const solution = (s, skip, index) => {
const filterAlphabet = [...alphabet].filter(el => !skip.includes(el));
const result = [...s].map(el => {
return filterAlphabet[(filterAlphabet.indexOf(el) + index) % filterAlphabet.length]
}).join("")
return result;
}
오우...