본문 바로가기

Algorithm & SQL/Programmers

[Programmers] [Python] 시저 암호

시저 암호


문제 설명


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

제한 조건


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

입출력 예


s n result
"AB" 1 "BC"
"z" 1 "a"
"a B z" 4 "e F d"

제출코드


import string
def solution(s, n): 
   answer = ''
   for i in range(len(s)):
       if s[i] == ' ':
               answer += ' '
       elif s[i] in string.ascii_uppercase:
           idx = string.ascii_uppercase.index(s[i])
           idx += n
           if idx >= len(string.ascii_uppercase):
               idx %= len(string.ascii_uppercase)
           answer += string.ascii_uppercase[idx]
       elif s[i] in string.ascii_lowercase:
           idx = string.ascii_lowercase.index(s[i])
           idx += n
           if idx >= len(string.ascii_lowercase):
               idx %= len(string.ascii_lowercase)
           answer += string.ascii_lowercase[idx]
   return answer

코드 설명


정말 문제 설명 그대로 구현하였다.

딱봐도 매우 비효율적이다..

만일, 효율성 테스트가 존재했더라면 아마 accept를 받지 못했을 것이다..

일단 accept했으니 코드를 설명해보겠다.

Line 1 : string 모듈 import

*Line 2 ~ 3 *: solution 함수와 answer변수 선언

*Line 4 *: 인자로 전달받은 string s의 길이만큼 순회한다.

Line 5 ~ 6 : 만일, s의 i번째 원소가 공백일 경우, answer변수에 공백을 추가한다.

Line 7 ~ 12 : s[i]가 영어 대문자일 경우, 해당 문자의 idx를 찾아 idx라는 변수에 저장한 뒤,
전달받은 인자 n값 만큼 더한다. 만일 idx 값이 uppercase의 길이보다 길다면
mod연산을 진행해준 다음 answer 변수에 uppercase[idx]문자를 answer변수에 추가한다.

Line 13 ~ 18 : s[i]가 영어 소문자일 경우, 해당 문자의 idx를 찾아 idx라는 변수에 저장한 뒤,
전달받은 인자 n값 만큼 더한다. 만일 idx 값이 lowercase의 길이보다 길다면
mod연산을 진행해준 다음 answer 변수에 lowercase[idx] 문자를 answer 변수에 추가한다.

Line 19 : answer변수를 반환한다.

다른 사람의 풀이


def caesar(s, n):
   s = list(s)
   for i in range(len(s)):
       if s[i].isupper():
           s[i] = chr((ord(s[i]) - ord('A') + n) % 26 + ord('A'))
       elif s[i].islower():
           s[i] = chr((ord(s[i]) - ord('a') + n) % 26 + ord('a'))

   return ''.join(s)

string내장 메서드 isupper()islower()를 이용해 대소문자를 판별하였다.

유니코드 값을 반환받는 ord를 이용해서 유니코드 값을 구하고 이를 chr의 인자로 전달하여 해당 유니코드에 매칭되는 문자를 구했다.

배운점


여태까지 영어 대소문자와 관련된 비교를 할 땐 항상 string.ascii를 이용하였는데

가능하다면 때에 따라 is.upper()is.lower()를 이용하는것이 좋은것 같다.

유니코드 값을 바탕으로 문자를 반환하는 chr()과 그 반대의 기능인 ord()의 기능을 다시 한번 배웠다.