[프로그래머스] 시저 암호 - Python

MinWoo Park·2021년 3월 23일
0

Algorithm

목록 보기
22/42
post-thumbnail

Algorithm Problem with Python — 22day


문제 설명 📖

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

제한사항

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

입출력 예


문제 이해 🔑

인풋으로 문자열과 정수가 주어집니다.
주어진 정수만큼 해당 문자열을 오른쪽으로 이동하는 문제입니다.
암호화하는 알고리즘을 작성하면 됩니다.


수도 코드 ✍️

  • 실패한 수도코드
  1. string 모듈을 통해 소문자와 대문자를 불러옵니다.
  2. for문을 통해 s의 첫 글자와 대(소)문자와 일치하는 곳을 찾고 n만큼 뒤로 이동하여 s의 길이만큼 슬라이싱합니다.
  • 모범 수도코드
    chr(), ord() 함수를 이용하여 코드를 작성합니다.
    chr(i)는 아스키(ASCII) 코드 값을 입력받아 그 코드에 해당하는 문자를 출력하는 함수,
    >>> chr(97) # 'a'
    ord(c)는 문자의 아스키 코드 값을 돌려주는 함수입니다.
    >>> ord('a') # 97
  1. 인풋으로 주어진 문자열을 리스트로 만듭니다.
  2. 리스트를 순회하면서 대소문자를 조건문을 통해 분기합니다.
  3. 리스트의 각 원소를 n만큼 오른쪽으로 이동시킵니다.
    3-1. ord(s[i]-ord('A') + n)는 s[i]의 아스키 코드 값을 구하고 'a'의 아스키 코드를 뺍니다.
    3-2. 그리고 이동시킬 만큼 n을 더합니다.
    3-3. 알파벳이 25글자이니 더 큰 수인 26으로 나머지 연산자를 이용하면 z의 경우처럼 맨 마지막이 다시 처음으로 돌아가는 경우의 수를 해결할 수 있습니다.
    3-4. 여기에 다시 'a'의 아스키 코드 값을 더하면 원하는 소문자의 아스키 코드 값을 구합니다.
    3-5. 구한 아스키 코드 값을 받아 문자로 변환하여 s의 i번 째에 재할당 합니다.
  4. 위 과정을 리스트가 끝날 때 까지 반복합니다.
  5. 마지막으로 join() 함수를 사용하여 리스트를 문자열로 바꿉니다.

코드 작성 ⌨️

  • 실패한 코드
import string 

def slicing(s, n, str):
    # print(s,n,str)
    for i in range(len(str)):
        if s[0] == str[i] and i != len(str)-1:
            return str[i+n : len(s)+1]
        elif s[0] == str[i] and i == len(str)-1:     
            return str[0+n-1 : len(s)]

def solution(s, n):
    answer = ''
    lowercase = string.ascii_lowercase # 소문자 abcdefghijklmnopqrstuvwxyz
    uppercase = string.ascii_uppercase # 대문자 ABCDEFGHIJKLMNOPQRSTUVWXYZ
    
    if s.islower():
        # for i in len(lowercase):
            # if s[0] == lowercase[i]:
                # return lowercase[i + n : len(s)]
                return slicing(s, n, lowercase)
    else:
        # for i in len(uppercase):
            # if s[0] == uppercase[i]:
                # return uppercase[i + n : len(s)]
                return slicing(s, n, uppercase)

  • 모범 코드
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)

정리 😄

제가 풀 땐 테스트 케이스 3번의 공백을 처리하지 못하여 어려움을 겪었는데 모범 코드를 통해 chr(), ord()함수를 알게 되었고 해당 함수들을 이용하면 공백을 무시하고 간단하게 문자만을 생각하여 계산할 수 있었습니다.
새로운 내장함수를 배웠으니 다음 응용문제에서 사용해 보아야 겠습니다.

profile
물음표를 느낌표로 바꾸는 순간을 사랑하는 개발자입니다.

0개의 댓글