어떤 문장의 각 알파벳을 일정한 거리만큼 밀어서 다른 알파벳으로 바꾸는 암호화 방식을 시저 암호라고 합니다. 예를 들어 "AB"는 1만큼 밀면 "BC"가 되고, 3만큼 밀면 "DE"가 됩니다. "z"는 1만큼 밀면 "a"가 됩니다. 문자열 s와 거리 n을 입력받아 s를 n만큼 민 암호문을 만드는 함수, solution을 완성해 보세요.
| s | n | return |
|---|---|---|
| "AB" | 1 | "BC" |
| "z" | 1 | "a" |
| "a B z" | 4 | "e F d" |
def solution(s, n):
answer = ''
for c in s:
if c == " ": answer += c
elif ord(c) >= 97: # 소문자 (97 ~ 122)
answer += chr((ord(c)+n-ord("a"))%26+ord("a"))
else: # 대문자 (65 ~)
answer += chr((ord(c)+n-ord("A"))%26+ord("A"))
return answer
이 문제에서의 가장 큰 어려움은 알파벳 범위를 넘었을 때, 넘은 만큼 다시 처음(a)로 돌아와야 한다는 점이었다.
이 문제를 해결하기 위해 ord(), chr()을 활용하며 chr((ord(c)+n-ord("a"))%26+ord("a")) 라는 수식으로 어떤 상황에서도 결과가 a ~ z 를 벗어나지 않도록 했다.
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)
긴 chr()과 ord()로 이어진 수식을 구성했을 때는 너무 조잡한 것 같아 걱정했으나 다른 분들의 코드 또한 크게 다르지 않다는 점에 심심한 위안을 받았었다.
이 코드는 그러한 코드 중 하나였는데, 나와 원리 자체는 같지만 isupper(), islower()라는 두 가지의 대소문자 판별 함수를 활용했다는 점이 인상적이었다.
두 함수의 존재 자체도 알지 못했기 때문에 이 함수를 통해 공백을 검사할 필요도 없었다는 점이 좋았다.
기본 라이브러리의 함수는 나의 생각보다 많은 기능이 포함되어 있어 아주 무궁무진하다는 것을 느꼈다.