영어 알파벳으로 구성된 문자열이 주어졌을 때, 각 알파벳을 알파벳 순서상 n칸 뒤에 있는 문자로 교체하는 것이 이번 과제입니다.
예를 들어 n = 1이라면 a는 b로, b는 c로 바뀌고, z는 다시 a로 순환됩니다.
문제 예시
입력 문자열과 이동 거리가 다음과 같다고 가정해 보겠습니다.
const str = "crazy"; const n = 1;
이때 기대되는 출력 결과는 다음과 같습니다.
alphabeticShift(inputString) = "dsbaz"
구현 방법
JavaScript에서는 charCodeAt()으로 문자를 ASCII 코드로 변환한 뒤 n만큼 더하고, String.fromCharCode()로 다시 문자로 되돌리는 방식으로 손쉽게 구현할 수 있습니다.
다만 단순히 코드 값에 n을 더하기만 하면 z를 넘어선 경우 알파벳 범위를 벗어난 문자가 출력되므로, 모듈로(%) 연산을 활용해 a~z 범위 안에서 순환하도록 처리해야 합니다.
개선된 코드
const str = 'crazy';
const alphabeticShift = (str = '', n = 1) => {
return str
.split('')
.map(ch => {
// 'a'(97)를 기준으로 0~25 범위로 정규화한 뒤 n칸 이동
const shifted = ((ch.charCodeAt(0) - 97 + n) % 26 + 26) % 26;
return String.fromCharCode(shifted + 97);
})
.join('');
};
console.log(alphabeticShift(str));
출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
dsbaz
코드 동작 원리
- charCodeAt(0): 각 문자의 ASCII 코드 값을 구합니다. 소문자 a는 97부터 시작합니다.
- 정규화: 97을 빼면 알파벳 위치가 0(a) ~ 25(z) 범위의 숫자로 변환됩니다.
- 순환 처리: n을 더한 뒤 26으로 나눈 나머지를 구하면 z를 넘어가도 다시 a부터 순환합니다. (+26 후 한 번 더 %26을 적용하면 음수 n도 안전하게 처리됩니다.)
- fromCharCode(): 다시 97을 더해 ASCII 코드로 만든 후 문자로 변환합니다.
대문자까지 지원하려면?
입력에 대문자가 포함될 가능성이 있다면, 해당 문자가 대문자인지 확인한 후 대문자는 'A'(65)를 기준으로 동일한 방식을 적용하면 됩니다.
const shiftChar = (ch, n) => {
const base = ch === ch.toUpperCase() ? 65 : 97;
const shifted = ((ch.charCodeAt(0) - base + n) % 26 + 26) % 26;
return String.fromCharCode(shifted + base);
};
이렇게 하면 대소문자와 관계없이 z→a, Z→A 순환이 정확하게 동작하는 알파벳 시프트 함수를 완성할 수 있습니다.