본문 바로가기
알고리즘/프로그래머스

[python] 시저 암호(연습문제)

by 민-Zero 2020. 5. 3.

문제의 목표는 간단하다 카이사르 암호라고도 불리는 가장 오래된 암호법인 치환 암호를 구현하면 된다. 주어진 매개변수 s가 'a'이고 n이 2라면 'a'를 2번 밀어낸 'c'로 치환되는 것이다. 'z'에서 1을 밀어내면 'A'가 되는 것이 아닌 다시 처음인 'a'로 되돌아간다. 즉, 소문자는 소문자에서만 대문자는 대문자에서만 공백은 공백으로 치환하면 된다.

 

설계 및 구현

구현을 위해 주어진 함수에는 암호문으로 변경해야 하는 평문이 담긴 매개변수 s와 해당 문자열의 문자를 몇 칸 밀어 암호문으로 변경할지 암호화 키 역할을 하는 매개변수 정수 n을 가진다. 

구현 내용을 생각해보면 주어진 정수 값에 의해 알파벳이 뒤로 밀려난다. 그러면 알파벳을 정수로 바꾼 아스키코드를 이용하여 주어진 정수를 더하여 아스키코드를 변경한 후 다시 문자로 변경하면 자동으로 문자를 치환하는 동작을 하며 a~z의 범위를 넘을 경우 다시 a부터 시작되므로 아스키코드 범위를 넘어설 경우 알파벳의 개수인 26만큼 빼주어 동일 코드 범위에서 반복되도록 하면 된다.

정리하면

① 소문자, 대문자 별로 아스키코드 범위 설정

② s의 문자들을 아스키코드 값으로 변경 후 대소문자 범위대로 나누어 주어진 n을 더한 뒤 다시 문자로 변환하여 반환 이때 대소문자 범위를 넘어갈 경우 -26을 통해 동일 구간에서 다시 밀어낼 수 있도록 한다.

③ 공백의 경우 그대로 공백으로 반환

 

①을 수행하기 위해 if elif 구문을 사용했다. a~z의 경우 아스키코드 값은 97~122를 가지고 A~Z의 경우 65~90의 범위를 가진다. 따라서 ord() 함수를 통해 문자를 아스키코드값으로 변환한 값을 비교하여 대소문자를 유지하고 치환하도록 한다.

②는 각 범위 내에서 n을 더한 값이 z, Z의 아스키코드값인 122, 90을 넘어가는지 확인하여 넘어가면 26을 빼준 코드값을 문자로 변환하고 아닐 경우 그대로 문자로 변환하여 반환한다.

③은 대소문자 이외의 경우는 무조건 공백이므로 else 구문을 사용하여 똑같이 공백을 반환하도록 한다.

 

위와 같은 과정을 거쳐 치환 암호의 기능을 구현할 수 있었다.

채점 또한 무리 없이 통과할 수 있었다.

 

※새롭게 배운 것

다른 사람의 풀이를 통해 굳이 아스키코드값으로 대소문자의 범위를 구분하지 않고 isupper(), islower() 함수를 통해 구분해도 된다는 것을 상기시킬 수 있었다. 또한 치환하기 위해 검색한 문자의 위치 자체의 문자만 교환하여 공백을 따로 추가하지 않고 기존의 문자열을 그대로 이용할 수 있다는 것을 알 수 있었다.

구간의 반복은 치환할 문자열의 아스키코드값을 대소문자의 시작 부분 아스키코드값에 빼주어 구간에서 몇 번째 알파벳인지 알아낸 후 n을 더해 얼마큼 밀어내면 되는지 확인한다 이때 %26을 통해 z, Z를 넘어가게 된다면 다시 구간 안으로 들어올 수 있도록 해준 뒤 A, a의 아스키코드값에 더해 치환을 수행하여 범위를 초과하는 경우도 한 번에 처리할 수 있다.

댓글