프로그래머스 lv.1_ 시저 암호

aydennote·2022년 4월 3일
1

Coding_TEST

목록 보기
2/6

안녕하세요 Ayden 입니다.

이번 문제는 완벽하게 풀지 못 했습니다. 풀어 보려고 약 4시간을 고민해봤으나, 결과적으로 테스트 케이스 6, 7, 8, 10, 12번을 통과 하지 못 하고 61.5점 받았습니다. 더 하다가는 장기적인 학습에 스스로 지칠 수 있어 다른 분이 푼 코드를 분석하는 데 더 집중하겠습니다.

1. 문제

문제 설명

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.

제한 조건

공백은 아무리 밀어도 공백입니다.
s는 알파벳 소문자, 대문자, 공백으로만 이루어져 있습니다.
s의 길이는 8000이하입니다.
n은 1 이상, 25이하인 자연수입니다.

입출력 예

2. 내 소스코드

function solution(s, n) {
    let arr = s.split("");
    let temp=[];
    let a=0;
    let answer = '';
        for(let x of arr){
        if(x===" "){
            temp.push(" ");
        } else{
            a= x.charCodeAt()+n; // 아스키코드 변환 및 +n
            if(123<=a || 90<a && a<97 ){
                a-=26;
                temp.push(String.fromCharCode(a));
            } else{
                temp.push(String.fromCharCode(a));
            }
        }
    }
    answer=temp.join("")
    return answer;
 }
let arr = s.split("");

문자열 s를 arr에 배열로 요소로 각각 저장합니다.
그렇게 저장된 배열을 for문을 사용하여 요소 하나씩 탐색합니다.


if(x===" "){
            temp.push(" ");
        }

탐색 중 공백을 만나면 공백 그대로 temp라는 배열에 저장시킵니다.


else{
    a= x.charCodeAt()+n; // 아스키코드 변환 후 +n

공백이 아니라면, 문자를 아스키코드로 변환한 후 a라는 변수에 이동 시킬 n만큼을 더하여 저장합니다.


 if(123<=a || 90<a && a<97 ){
                a-=26;
                temp.push(String.fromCharCode(a));
            } 

이동되는 수인 n을 아스키코드에 더 한 값이 알파벳 아스키코드 범위 밖같이면 -26을 한 후에 다시 문자로 바꿔 temp 배열에 저장시킵니다.


else{
 		temp.push(String.fromCharCode(a));
    }

이동되는 수인 n을 아스키코드에 더 한 값이 알파벳 아스키코드 범위 내라면 그대로 문자로 바꿔 temp 배열에 저장시킵니다.


answer=temp.join("")
    return answer;

temp에 저장된 배열들을 answer에 문자로 저장시킨 후 return 합니다.

3. 다른 사람 풀이

function solution(s, n) {
   let answer = "";

 for (let x of s){        
   if (x === ' ' ) 
    answer += ' ';
   else 
       answer += String.fromCharCode( (x.charCodeAt()>90)?
     (x.charCodeAt()+n-97)%26+97 : (x.charCodeAt()+n-65)%26+65 )     
 }

   return answer;
}

처음 이 문제를 봤을 때, 아스키코드가 먼저 떠올라 아스키코드 풀이로 학습하겠습니다.


for (let x of s){        
   if (x === ' ' ) 
    answer += ' ';

s 문자열을 요소 하나씩 확인하여 공백이 있다면 공백을 answer에 추가합니다.


else 
       answer += String.fromCharCode( (x.charCodeAt()>90)?
     (x.charCodeAt()+n-97)%26+97 : (x.charCodeAt()+n-65)%26+65 ) 

x 요소가 공백이 아닌 경우, 삼항 연산을 사용하여 아스키코드로 변환합니다. 코드들을 글로 정리하자면 아래와 같습니다.

(변환한 아스키 코드 값이 90↑) ? 
(변환한 아스키 코드 값+거리- 'a'아스키 코드 값)%(소문자 알파벳 수)+
'a'아스키 코드 값 : (변환한 아스키 코드 값+거리-'A'아스키 코드 값)
%(대문자 알파벳 수)+'A'아스키 코드 값

4. 마무리

제 풀이의 문제는 대문자 알파벳 아스키 코드에서 거리가 n만큼 이동 됐을 때, 소문자 알파벳 범위로 넘어가는 경우가 있습니다.
대문자 알파벳은 대문자 루프를 돌고, 소문자는 소문자 루프를 돌면 해결 되는 문제입니다.

function solution(s, n) {
    let arr = s.split("");
    let temp=[];
    let a=0;
    let answer = '';
        for(let x of arr){
        if(x===" "){
            temp.push(" ");
        } else{
            a= x.charCodeAt()+n; // 아스키코드 변환 및 +n
            if(65<=x.charCodeAt()&& x.charCodeAt()<=90){ // 대문자
                if(a>=91){ // 대문자 범위를 벗어나는 경우
                    a=((a-65)%26+65); // 대문자에서 소문자 아스키로 넘어가는 경우 다시 대문자 아스키로 전환 
                    temp.push(String.fromCharCode(a));
                } else{
                    temp.push(String.fromCharCode(a));
                }
            } else if(97<=x.charCodeAt() && x.charCodeAt()<=122){
                if(a>=123){
                    a=((a-97)%26+97);
                    temp.push(String.fromCharCode(a));
                }
                else{
                    temp.push(String.fromCharCode(a));
                }
             }
            } 
        }
        answer=temp.join("")
        return answer;
    }

다른 사람 풀이를 보고 제 코드를 수정하였습니다. 중복 if 문를 많이 써서 효율성, 가독성 없는 코드이며, 추후 더 학습하여 다시 풀어 보겠습니다.

profile
기록하는 개발자 Ayden 입니다.

2개의 댓글

comment-user-thumbnail
2022년 4월 4일

와우.. 이게 프로그래머스 레벨1 이라니..!!
어려워 보이지만 ayden님 설명을 보고 차근차근 이해 해보도록 할게요!!!

1개의 답글