📢 문제 설명
어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.
⛔ 제한 조건
공백은 아무리 밀어도 공백입니다.
s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
s의 길이는 8000이하입니다.
n은 1 이상, 25이하인 자연수입니다.
const s = "a B z"
const n = 4;
//다른 케이스 확인
//const s = "p";
//const n = 15;
solution(s, n);
function solution(s, n) {
let num = 0;
let str = "";
let answer = "";
let answerArr = [];
let arr = s.length > 1 ? s.split("") : s;
for (let i = 0; i < arr.length; i++) {
if (arr[i] === " ") {
str = " ";
}
//z,Z 케이스
else if (arr[i] === "z" || arr[i] === "Z") {
let newNum = arr[i].charCodeAt(0);
let newStr = String.fromCharCode(
newNum - ("Z".charCodeAt(0) - "A".charCodeAt(0)) + n - 1
);
str = newStr;
} else {
num = arr[i].charCodeAt(0) + n;
if (num < "Z".charCodeAt(0) && num < "z".charCodeAt(0)) {
//제일 큰 수를 기준으로 작은 경우에만 num 정상 출력
str = String.fromCharCode(num);
} else {
if (arr[i] === arr[i].toLowerCase()) {
//대소문자 구별해서 소문자 케이스
str =
num > "z".charCodeAt(0)
? String.fromCharCode(
"a".charCodeAt(0) + (num - "z".charCodeAt(0) - 1)
)
: String.fromCharCode(num);
} else {
str =
num > "Z".charCodeAt(0)
? String.fromCharCode(
"A".charCodeAt(0) + (num - "Z".charCodeAt(0) - 1)
)
: String.fromCharCode(num);
}
}
}
answerArr.push(str);
}
answer = answerArr.join("");
return answer;
}
문자열 (s)의 길이가 1 이상일 때 배열, 아닌 경우 arr로 선언한다.
for문으로 arr[i]번째에 공백이 있는 경우, 해당 공백은 아스키 코드로 변환하지 않는다.
조건1
arr[i]가 z,Z 인 경우 n = 1 이상일 때 z + n의 문자열은 'a'부터 시작된다.
해당 arr[i]의 charCodeAt() 구한다.
z > a 순으로 시작해야되기 때문에 a 부터 시작하고, n을 더한 후 -1 한다.
"z".charCodeAt(0) - "a".charCodeAt(0) + n - 1
조건2
num = arr[i].charCodeAt(0) + n;
해당 배열에 맞게 구해줌str = String.fromCharCode(num);
> 기본 반환arr[i] === arr[i].toLowerCase()
대/소문자 구별answerArr.push(str)
answer = answerArr.join("");
return answer;
📌 charCodeAt()
str.charCodeAt(index)
메서드는 주어진 인덱스에 대한 UTF-16 코드를 나타내는 0부터 65535 사이의 정수를 반환합니다.
📌 String.fromCharCode()
String.fromCharCode(num1[, ...[, numN]])
메서드는 UTF-16 코드 유닛의 시퀀스로부터 문자열을 생성해 반환합니다.
function solution(s, n) {
let chars =
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY ";
return s
.split("")
.map((e) => chars[chars.indexOf(e) + n])
.join("");
}
map()
으로 꺼내서 chars.indexOf(e)
로 위치를 찾는다.e+n
join('');
return answer
; function solution(s, n) {
let upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let lower = "abcdefghijklmnopqrstuvwxyz";
let answer = "";
for (let i = 0; i < s.length; i++) {
let text = s[i];
if (text == " ") {
answer += " ";
continue;
}
let textArr = upper.includes(text) ? upper : lower;
let index = textArr.indexOf(text) + n;
if (index >= textArr.length) index -= textArr.length;
answer += textArr[index];
}
return answer;
}
answer += " "
//공백 수 만큼 돌리기 continue;
let textArr = upper.includes(text) ? upper : lower;
//text가 있는지 없는지로 소문자인지 대문자인지 비교let index = textArr.indexOf(text) + n;
//배열에서 text index + ntestArr[index]
의 모든 index 꺼내기return answer
;function solution(s, n) {
let answer = "";
const upperMinAscii = 65;
const upperMaxAscii = 90;
const lowerMinAscii = 97;
const lowerMaxAscii = 122;
const asciiArray = Array.from(s).map((item) => {
let ascii = item.charCodeAt(0);
const isWhite = item === " ";
if (isWhite) {
return ascii;
}
const isNotAlpahbet =
!(ascii >= upperMinAscii && ascii <= upperMaxAscii) &&
!(ascii >= lowerMinAscii && ascii <= lowerMaxAscii);
if (isNotAlpahbet) {
return ascii;
}
const isUpper = ascii < lowerMinAscii;
const min = isUpper ? upperMinAscii : lowerMinAscii;
const max = isUpper ? upperMaxAscii : lowerMaxAscii;
ascii += n;
if (ascii > max) {
return (ascii % max) + min - 1;
}
return ascii;
});
answer = String.fromCharCode.apply(null, asciiArray);
console.log(answer);
return answer;
}
📌 apply()
func.apply(thisArg, [argsArray])
주어진 this 값과 배열(또는 유사 배열객체)로 제공되는 arguments로 함수를 호출합니다.
📍thisArg
: func을 호출하는데 제공될 this의 값. 메소드에 의해 실제로 보여지는 값이 아닐 수 있음 주의 !
메소드가 non-strict mode 코드의 함수일 경우,null
과undefined
가 전역 객체로 대체 되며, 기본 값은 제한합니다.
📍argsArray
: func이 호출되어야 하는 인수를 지정하는 유사 배열 객체, 함수에 제공된 인수가 없을 경우null
orundefinded
배열대신 제네릭 유사 배열 객체로 사용 될 수 있음
📍 반환 값 : 지정한this
_값과 인수들로 호풀한 함수의 결과
apply
는 지원되는 인수의 타입만 제외하면 call()
과 매우 유사합니다. 인수(파라미터)의 리스트 대신 인수들의 배열을 사용할 수 있습니다.
또한 apply를 사용해, 배열 리터럴이나( 예 func.apply(this, ['e','a])
, Array 객체 예 (func.apply(this , new Array('e', 'a'))
를 사용 할 수 있습니다. args array
파라미터를 위한 argments
를 사용 할 수도 있습니다. arguments
는 함수의 지역변수 입니다. 이는 호출된 객체의 지정되지 않은 모든 인수에 대해 사용할 수 있습니다.
따라서 apply
메소드를 사용할 때 호출된 객체의 인수를 알 필요가 없습니다. argments
를 사용해 모든 인수들을 호출된 객체로 전달 할 수 있습니다. 그럼 호출된 객체는 그 인수들을 처리할 수 있게됩니다.
ECMAscript 5 (chrome 14, ie 9 지원 X):
모든 유사 배열 객체 타입을 사용 할 수 있으며, 실제로 이는 프로퍼티 length와 범위 (0..length-1)
내의 정수 프로퍼티를 갖는다는 것을 의미합니다.
예를 들면 이제 nodelist
또는 {'length': 2, '0' : 'e', '1' : 'banana'}
와 같은 커스텀 객체를 사용 할 수 있습니다.
📌 answer = String.fromCharCode.apply(null, asciiArray);
null을 사용 한 이유 :
이미 존재하는 함수를 호출할 떄 다른 this 객체를 할당 가능
this
는 현재 객체, 호출하는 객체를 참조합니다. apply를 사용해, 새로운 객체마다 다른 객체에 상속시킬 수 있음