
이 문제를 처음 봤을 때는 아스키 코드로 접근하는 방법 외의 다른 방법은 딱히 떠오르지 않았다.
이마저도 한 번에 풀지는 못했지만... ai의 도움을 받아 완성한 나의 코드는 다음과 같다.
1) 문자열 s를 하나씩 순회한다
2) 공백이면? 아무것도 하지 않는다.
3) 대문자면? 대문자 범위 (65~90) 내에서 움직이되, 90('Z')을 넘으면 65('A')로 돌아온다.
4) 소문자면? 소문자 범위 (97~122) 내에서 움직이되, 122('z')를 넘으면 97('a')로 돌아온다.
5) 변환된 값들을 배열에 담은 뒤에 'join('')'으로 합친다.
- A: 65, a: 97, 공백(" "): 32
- charCodeAt(인덱스): 문자 -> 아스키 코드로 변환하는 함수
- String.formCharCode(숫자): 아스키 코드 -> 문자로 변환하는 함수
function solution(s, n) {
let result = [];
for (let i=0; i<s.length; i++) {
let char = s[i];
// 1. 공백인 경우
if (char === ' ') { // 빈 문자열이 아니고 공백이기 때문에 꼭 띄워줘야 함!
result.push(' ');
continue;
}
// 2. 아스키 코드 확인
let code = char.charCodeAt(0); // 이미 char은 인덱스 i를 담고있는 한 글자짜리 문자이므로 0
// 3. 대문자인 경우
if (code >= 65 && code <= 90) {
let shifted = code + n;
if (shifted > 90) shifted -=26; // 알파벳은 총 26개이므로, 만약 범위를 넘어가는 경우 다시 돌아오게 하기
result.push(String.fromCharCode(shifted));
}
// 4. 소문자인 경우
if (code >= 97 && code <= 122) {
let shifted = code + n;
if (shifted > 122) shifted -=26;
result.push(String.fromCharCode(shifted));
}
}
return result.join('');
}
하지만 다른 사람들의 풀이를 보고 나니 아스키 코드를 다룰 필요 없이, 훨씬 더 가독성 있게 이 문제를 풀 수 있는 방법을 알게 되었다. 그건 바로 대문자와 소문자가 순서대로 적힌 문자열을 미리 만들어두는 것이다!
1) 대문자 모음("ABC...Z")과 소문자 모음("abc...z")을 변수에 각각 저장한다.
2) 현재 문자가 대문자인지 소문자인지 찾는다.
3) 현재 문자가 몇 번째 인덱스인지 찾는다.
4) 해당 인덱스에 n을 더한 뒤, 전체 길이인 26으로 나눈 나머지 위치에 있는 문자를 가져온다.
function solution(s, n) {
const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const lower = "abcdefghijklmnopqrstuvwxyz";
let result = "";
for (let char of s) {
// 1. 공백인 경우
if (char === " ") {
result += " "; // 문자열이므로 push가 아닌 덧셈 연산
continue;
}
// 2. 현재 문자가 대문자인지 소문자인지 확인
const textArr = upper.includes(char) ? upper : lower;
// 3. 현재 문자의 위치(index)를 찾고 n만큼 이동
// (index + n) % 26을 하면 z를 넘어가도 다시 a로 돌아옴
let index = textArr.indexOf(char);
let nextIndex = (index + n) % 26;
result += textArr[nextIndex];
}
return result;
}
for (let char of s)
for... of: 문자열 s에서 한 글자씩 순서대로 꺼내 변수 char에 담아주는 역할을 한다. // 1. 공백인 경우
if (char === " ") {
result += " "; // 문자열이므로 push가 아닌 덧셈 연산
continue;
}
continue;를 통해 아래 코드들을 실행하지 않고, 바로 다음 char에 대한 조건문을 실행한다. // 2. 현재 문자가 대문자인지 소문자인지 확인
const textArr = upper.includes(char) ? upper : lower;
upper.includes(char)을 통해 현재 글자가 대문자 문자열 안에 들어있는지 확인한다. // 3. 현재 문자의 위치(index)를 찾고 n만큼 이동
// (index + n) % 26을 하면 z를 넘어가도 다시 a로 돌아옴
let index = textArr.indexOf(char);
let nextIndex = (index + n) % 26;
indexOf(char): 현재 글자가 알파벳 순서상 몇 번째 인덱스인지 찾는다. (예: 'A'는 0)index + n: 현재 위치에서 문제에서 주어진 거리 n만큼 오른쪽으로 이동한다.% 26: 이 부분이 아주 중요!result += textArr[nextIndex];
...
return result;
nextIndex 위치에 있는 글자를 textArr에서 꺼내 결과 문자열에 붙인다.