URL : https://school.programmers.co.kr/learn/courses/30/lessons/12926
JS
문제
어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.
제한 조건
공백은 아무리 밀어도 공백입니다.
s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
s의 길이는 8000이하입니다.
n은 1 이상, 25이하인 자연수입니다.
계획
알파벳 배열을 적고
/*문자열 변형시 인덱스+n한 값이 z의 인덱스보다 크면(배열을 벗어나면) z의 인덱스값만큼을 뺸 값을 인덱스값으로 사용하는 값(알파벳)을 가져옴*/
문자열을 아스키코드로 변환하고 변환값에 n만큼 더하고 다시 문자열 만들기
대소문자 구분하고 공백은 따로 처리 해주기
참고, 풀이
문자 → 아스키코드
String.charCodeAt()
String.charCodeAt(index)
아스키코드 → 문자
String.fromCharCode()
String.fromCharCode(num1[, ...[, numN]])
대 소문자 유지
1. 소문자 처리 코드
let charCode = "a".charCodeAt(0); // 97
let n = 2;
let result = String.fromCharCode(((charCode - 97 + n) % 26) + 97);
console.log(result); // "c"
if (charCode >= 97 && charCode <= 122) {
return String.fromCharCode(((charCode - 97 + n) % 26) + 97);
}
- 조건 확인 (charCode >= 97 && charCode <= 122)
- charCode가 소문자 알파벳의 아스키코드 범위(97~122)에 있는지 확인.
- 예: a=97, z=122.
- 문자를 0~25 범위로 변환 (charCode - 97)
- 소문자의 아스키코드를 97을 기준으로 0부터 시작하는 숫자로 변환.
- 예: a=0, b=1, ..., z=25.
- 시프트(+ n)
- 변환된 숫자에 n(주어진 이동 값)을 더해 새로운 위치를 계산.
- 예: a(0)에서 n=2를 더하면 2가 되어 c로 이동.
- 순환 처리 (% 26)
- 26으로 나눈 나머지를 사용해 범위를 벗어나지 않도록 순환.
- 예: z(25)에서 n=2를 더하면 27이 되는데, 27 % 26 = 1로 순환하여 b로 변환.
- 아스키코드로 복원 (+ 97)
- 다시 원래 소문자 범위로 복원하기 위해 97을 더함.
- 예: 0이 a가 되고, 25가 z가 됨.
- 문자 반환 (String.fromCharCode)
- 최종 계산된 아스키코드를 문자로 변환해 반환.
2. 대문자 처리 코드
let charCode = "Z".charCodeAt(0); // 90
let n = 2;
let result = String.fromCharCode(((charCode - 65 + n) % 26) + 65);
console.log(result); // "B"
if (charCode >= 65 && charCode <= 90) {
return String.fromCharCode(((charCode - 65 + n) % 26) + 65);
}
- 조건 확인 (charCode >= 65 && charCode <= 90)
- charCode가 대문자 알파벳의 아스키코드 범위(65~90)에 있는지 확인.
- 예: A=65, Z=90.
- 0~25 범위로 변환 (charCode - 65)
- 대문자의 아스키코드를 65를 기준으로 0부터 시작하는 숫자로 변환.
- 예: A=0, B=1, ..., Z=25.
- 시프트(+ n)
- 변환된 숫자에 n을 더해 새로운 위치를 계산.
- 예: A(0)에서 n=3을 더하면 3이 되어 D로 이동.
- 순환 처리 (% 26)
- 26으로 나눈 나머지를 사용해 범위를 벗어나지 않도록 순환.
- 예: Z(25)에서 n=2를 더하면 27이 되고, 27 % 26 = 1로 순환하여 B로 변환.
- 아스키코드로 복원 (+ 65)
- 다시 원래 대문자 범위로 복원하기 위해 65를 더함.
- 예: 0이 A가 되고, 25가 Z가 됨.
- 문자 반환 (String.fromCharCode)
- 최종 계산된 아스키코드를 문자로 변환해 반환.
답
function solution(s, n) {
let answer = [...s].map((element) => {
if (element === " ") return " "; // 공백은 그대로 반환
let charCode = element.charCodeAt(); // 문자 -> 아스키코드드
// 소문자 처리
if (charCode >= 97 && charCode <= 122) {
return String.fromCharCode(((charCode - 97 + n) % 26) + 97);
}
// 대문자 처리
if (charCode >= 65 && charCode <= 90) {
return String.fromCharCode(((charCode - 65 + n) % 26) + 65);
}
return element; // 알파벳이 아닌 경우 그대로 반환
});
return answer.join(""); // 배열을 문자열로 결합
}
코드 간략화하기
function solution(s, n) {
return [...s].map(char => {
if (char === " ") return char; // 공백은 그대로 반환
const base = char >= "a" ? 97 : 65; // 소문자와 대문자의 ASCII 기준값
return String.fromCharCode(((char.charCodeAt() - base + n) % 26) + base);
}).join("");
}
다른사람 코드
function solution(s, n) {
return s.split('').map(char => {
if (char === ' ') {
return char; // 공백은 그대로 반환
}
const charCode = char.charCodeAt(0);
let base = char >= 'a' ? 97 : 65; // 소문자는 97, 대문자는 65가 기준
return String.fromCharCode((charCode - base + n) % 26 + base);
}).join('');
}
function solution(s, n) {
return s.replace(/[a-zA-Z]/g, char =>
String.fromCharCode((char.charCodeAt(0) - (char < 'a' ? 65 : 97) + n) % 26 + (char < 'a' ? 65 : 97))
);
}
function solution(s, n) {
var chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY "
return s.split('').map(e => chars[chars.indexOf(e)+n]).join('');
}
cf.
아스키코드 ↔ 문자
: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/charCodeAt
문자 ↔ 아스키코드
: https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode
다른사람 코드