본문 바로가기
코테

[JS] 시저 암호

by zenna 2024. 4. 15.
728x90
점수 : 1147(+8)
테스트케이스 최대 소요시간 : 3.00ms, 33.9MB

 

문제 : https://school.programmers.co.kr/learn/courses/30/lessons/12926?language=javascript

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

제출답안

function solution(s, n) {
    const sToInt = {a:0,b:1,c:2,d:3,e:4,f:5,g:6,h:7,i:8,j:9,k:10,l:11,m:12,n:13,o:14,p:15,q:16,r:17,s:18,t:19,u:20,v:21,w:22,x:23,y:24,z:25};
    const intToS = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];

    const cizer=(chr)=>{
        if(chr==' ') return ' ';
        let ns1 = chr.toLowerCase();
        let num = sToInt[ns1]+n;
        num = (num>25)?num-26 : num;
        return (ns1==chr)?intToS[num]:intToS[num].toUpperCase();
    }
    return [...s].map((s1,index)=>cizer(s1)).join('');
    
}

 

문제해설

2~3. intToS 배열에서 indexOf를 사용하면 sToInt 해시를 사용하지 않아도 됐지만, 문자열 최대 길이가 3000이고 알파벳 26개를 탐색해야 하기 때문에 더 빨리 탐색할 수 있는 hash를 사용했다.

 

5. 뒤에서 return문에 map으로 반환받은 배열을 사용하기 위해 함수 내부에 별도로 cizer변환 메서드를 선언했다. map 함수 사용 시 `{}`를 사용하면 null이 반환된다는 걸 얼마 전에 알았다 ㅠ

 

6. 확인하는 문자가 공백인 경우 공백을 바로 반환하도록 선언

 

7. 대소문자를 구분하기 위해 대문자 배열과 소문자 배열을 각각 선언하고 include나 indexOf로 소문자 배열에서의 포함여부를 확인하고, 없으면 대문자 배열에서 찾는 식의 풀이도 있었는데, 이러면 Z를 찾을 때 52번이나 일치 여부를 확인해야 한다. 따라서 무조건 문자를 소문자로 바꾸고, 10라인의 리턴문에서 바꾼 문자와 기존 문자가 일치하면 기존 문자가 소문자이니 유지하고 다르면 마지막에 대문자로 변환해주는 방식을 선택했다. 

 

8~9. 시저암호문이 적용된 문자를 찾는다. 다만 기존 문자의 숫자에 n을 더한 값이 25보다 큰 경우 배열 앞부분으로 돌아간 것이기 때문에 26을 빼주었다. n이 25까지로 제한되어 있어 무관했던 방식. 이 제한조건을 잘 사용해서 abcdefg....를 여러번 반복한 배열을 선언해버리고 index에 더해준 사람들도 많았다. a와 25가 주어진 경우 25번째 인덱스의 z를 찾아주는 식. 효율 면에서 확실하다면 하드코딩이 제일 정확하다고 생각하는 편이라 이런 방식도 괜찮은 것 같다. 아래 방식으로 풀게 되면 최대 소요 시간이 1.4ms대로 매우 빨랐다.

function solution(s, n) {
    var chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXY                          "
    return s.split('').map(e => chars[chars.indexOf(e)+n]).join('');
}

 

12. [...s] 를 통해 s를 한 글자씩 자른 배열로 변환 후, map을 사용해서 cizer변환한 문자들로 이루어진 배열로 리턴받고, 다시 그 배열을 join으로 문자열 변환해줬다.

 


후기 : 자바였으면 char에 해당하는 번호를 사용해서 (아스키코드..?) 푸는 방식으로 했을 것 같은데

자바스크립트는 형 변환 없이 직관적으로 작성하니 사실 취향에 더 맞았다. 역시 자스가 최고야.

다만 이 방식으로 푸신 분이 있었는데 시간면에서도 효율적이어서 적어둠!

function caesar(s, n) {
  return s.replace(/([a-z])|([A-Z])/g, (c, lowerCase) => {
    var startCode = lowerCase ? 'a'.charCodeAt(0) : 'A'.charCodeAt(0)
    return String.fromCharCode((c.charCodeAt(0) - startCode + n) % 26 + startCode)
  })
}

 

728x90

'코테' 카테고리의 다른 글

[JS] 약수의 합  (0) 2024.04.16
[Java] 정수 제곱근 판별  (0) 2024.04.11
[JS] 성격 유형 검사 (해설포함)  (0) 2024.04.10
[java] 붕대감기 (해설포함)  (1) 2024.04.09
[Java] 없는 숫자 더하기  (0) 2024.04.08

댓글