
function solution(s, n) {
const arr = [...s];
// UTF-16 코드를 담을 배열
let charCode = [];
for (let i = 0; i < s.length; i++) {
let code = s[i].charCodeAt();
// 대문자 경우
if (code >= 65 && code <= 90) {
code + n > 90 ? charCode.push(code + n - 26) : charCode.push(code + n);
}
// 소문자인 경우
if (code >= 97 && code <= 122) {
code + n > 122 ? charCode.push(code + n - 26) : charCode.push(code + n);
}
// 공백인 경우
if (code === 32) {
charCode.push(code);
}
}
// UTF-16을 다시 문자열 생성해서 반환
return String.fromCharCode(...charCode);
}
우선, 문제를 보자마자 유니코드라는 단어가 떠올랐다. 유니코드에 대해서 찾아보니 아스키(ASCII) 코드를 알게 되었다. 그리고 UTF-16에 대해서 알게 되었고, 이를 자바스크립트에서는 charCodeAt()과 fromCharCode()라는 메서드를 사용하여 활용할 수 있다는 것을 알게 되었다.
charCodeAt() 은 주어진 인덱스에 대한 UTF-16 코드를 나타내는 0부터 65535 사이의 정수를 반환하는 메서드이며 아래와 같이 작성한다. 반환값은 주어진 인덱스 대한 문자에 대한 UTF-16 코드를 나타내는 숫자이다.
str.charCodeAt(index)
fromCharCode() 는 UTF-16 코드 유닛의 시퀀스로부터 문자열을 생성해 반환하며 매개변수로는 숫자 뭉치를 사용한다.
String.fromCharCode(num1[, ...[, numN]])
어떤 메서드를 사용할지 파악한 뒤, 콘솔에 하나씩 찍어보면서 소문자의 아스키 코드, 대문자의 아스키 코드, 그리고 공백의 아스키 코드를 파악하였다. 이 문제에서 주의해야할 점은 소문자는 소문자끼리 순환하고, 대문자는 대문자끼리 순환한다는 것이었다.
대문자의 아스키 코드는 65부터 90까지, 총 26개이며, 소문자의 아스키 코드는 97부터 122까지 역시 총 26개이다. 만약 "P"를 15만큼 밀었을 때를 가정해보자면, 우리가 원하는 답은 "E"이다. "P"의 아스키 코드는 80이고, 15를 더하면 95라는 숫자가 나온다. 하지만 95에 해당하는 문자열은 "_"이기 때문에 우리가 원하는 답을 얻을 수 없게 된다. "E"의 아스키 코드는 69이며, 이를 얻기 위해서는 80에서 15를 더한 다음, 알파벳의 개수인 26만큼 빼야한다. 이를 차용하여, 코드를 작성하였다.
대문자를 n만큼 밀었을 때의 아스키 코드가 Z 아스키 코드인 90을 초과하는 경우에는 26만큼 빼주고, 소문자를 n만큼 밀었을 때의 아스키 코드가 z 아스키 코드인 122를 초과하는 경우에도 26만큼 빼는 방식이다.
마지막으로 조금 헤맸던 부분이 있었다. fromCharCode() 메서드의 매개변수에 숫자 뭉치를 넣어야 하는데, 이를 이해하지 못하고 자꾸만 매개변수의 인자로 다른 것들을 넣고 있었다. 그래도 콘솔에 하나씩 찍어보고, 구글링하면서 spread syntax를 사용하여 원하는 답을 반환할 수 있었다.
function solution(s, n) {
var upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var lower = "abcdefghijklmnopqrstuvwxyz";
var answer= '';
for(var i =0; i <s.length; i++){
var text = s[i];
if(text == ' ') {
answer += ' ';
continue;
}
var textArr = upper.includes(text) ? upper : lower;
var index = textArr.indexOf(text)+n;
if(index >= textArr.length) index -= textArr.length;
answer += textArr[index];
}
return answer;
}
아스키 코드를 사용하지 않고 푼 최선의 방법인 것 같다. 문자열의 인덱스를 사용하였고 그 인덱스를 넘어간 경우엔 문자열의 길이만큼 빼주는 방법.... 최고라고 생각한다.