본문 바로가기

프로그래밍/코드분석

[파이썬] level3 시저암호

(level3)시저암호

문제

어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다.
A를 3만큼 밀면 D가 되고 z를 1만큼 밀면 a가 됩니다. 공백은 수정하지 않습니다.
보낼 문자열 s와 얼마나 밀지 알려주는 n을 입력받아 암호문을 만드는 ceasar 함수를 완성해 보세요.
“a B z”,4를 입력받았다면 “e F d”를 리턴합니다.

나의 접근법

이상하게 쉽게 풀릴 것 같았는데, 하루정도 걸려서 풀었다. 가장 직관적으로 떠오른 생각은 아스키코드(ASCII) 코드를 활용하자는 것이다. 아스키코드가 뭔지 잘 모른다면, 쑥쓰러운 나의 블로그 포스팅 아스키코드와 유니코드의 이해 을 소개한다.

문제를 풀 때 가장 먼저 고려했던 것은

  1. 공백을 반영해야 한다는 것.

    • a b c라고 입력한 뒤, 2칸을 밀어야 한다면 cde가 아닌 c d e로 출력되어야 한다.
  2. 대문자와 소문자를 구별해야 한다.

    • a b cc d e로, A B CD E F로 출력되어야 한다.
  3. 알파벳의 개수는 26개다. 그런데 30칸을 밀어야 할 때도 고려해야 한다.

새롭게 배운 메서드

입력받은 문자의 아스키코드 값(int)를 알아내는 메서드를 익혀야 했고, 역으로 아스키코드 값(int)를 문자로 출력하는 메서드도 익혀야 했다.

  1. 문자 --> 아스키코드 ord
    구글에 python string to ascii로 검색했다. 다음 스택오버플로를 참고했다.
    스크린샷, 2017-09-03 15-21-45

    ord()안에는 문자가 들어가야 한다.

  2. 아스키코드 --> 문자 chr
    스크린샷, 2017-09-03 15-22-45

    chr()안에는 숫자가 들어가야 한다.

부딪혔던 난관들

  1. caesar(s, n)에서 n이 26이 넘는 걸 먼저 고려했다. n = n % 26으로 반영했다.

  2. z에서 2칸을 밀면 b가 출력되어야 한다. 이 경우에는 알파벳의 범위를 넘어서니까 a부터 시작하면 되겠네! 라고 생각했다.

  3. chr(ord('a') + n)이라고 생각했다.

    • 이 경우에 "x y z"를 입력하고 n = 5이면 f f f가 출력되는 불상사가 생겼다.
    • z의 범위가 넘어서게 되면 a에서 똑같이 n을 더해주기 때문이다.
  4. 생각을 다시 고쳐먹어야 했다. 입력받은 문자가 몇번째인지 순서 를 알아내야 했다!

  5. 알파벳이 몇번째 있는 값인지를 고려해서 코드를 수정했다.

    caesar = chr((ord(s[char]) + n - 26))
    

    일단 입력받은 값을 n만큼 밀어주고, 알파벳 개수만큼 빼주면 순서가 반영된다.

나의 풀이

def caesar(s, n):
    n = n % 26
    caesar_list = []

    for char in range(0, len(s)):

        caesar = chr(ord(s[char]) + n) # 'Z' 또는 'z'를 넘어서는 것인지 확인하기 위함

        if s[char] == " ": # 공백 처리
            caesar_list.append(" ")
            continue

        if s[char].isupper(): # 대문자 처리
            if caesar > chr(ord("Z")):
                caesar = chr((ord(s[char]) + n - 26))
        else: # 소문자 처리
            if caesar > chr(ord("z")):
                caesar = chr((ord(s[char]) + n - 26))

        caesar_list.append(caesar)
    result = "".join(caesar_list) # 리스트를 문자열로 만들어줌
    return result

# 실행을 위한 테스트코드입니다.
print('s는 "a B z", n은 4인 경우: ' + caesar("a B z", 4))

문제 출처

https://programmers.co.kr/learn/challenge_codes/23