1. 문제
해빈이는 준규에게 메세지를 받았다. 준규는 세계 최고 수준의 암호학자이기 때문에 해빈이에게 암호로 메세지를 보낸다. 이번에 준규는 One Time Pad(OTP) 암호화 방식을 사용하기로 했다. 준규는 OTP방식을 제대로 적용하면 절대 해독할 수 없다는 것을 알기 때문에, 해빈이가 해석할 수 있도록 몇 가지 힌트를 같이 보내기로 했다.
준규는 메세지에 항상 영소문자, 온점('.'), 공백 (' ', ASCII코드 32)만 쓴다. 그리고 key값으로는 항상 '0'부터 '9'까지의 숫자만 쓴다. 이 사실을 알고 있는 해빈이는 이를 이용해 메세지에 있는 온점과 공백의 위치를 알 수 있다는 것을 깨닫고, 당신에게 프로그램으로 만들어달라고 부탁했다.
준규가 이런 메세지를 보낸 게 한두 번이 아니기 때문에 해빈이는 OTP 암호화 방식을 알고 있다. 예를 들어 "0120123"을 key로 사용해서 "abc efg"라는 문자열을 암호화하면 아래와 같다.
abc def 0120123 |
61 62 63 20 65 66 67 30 31 32 30 31 32 33 |
51 53 51 10 54 54 54 |
Start | ASCII hexadecimal | excrypted message |
먼저 key와 메세지 원문을 ASCII 인코딩을 사용해 16진수로 변환한다. 그리고 변환한 key와 원문을 각각 차례대로 XOR 연산한다. 그 결과가 암호화 된 메세지이다.
2. 입력
입력에 첫 줄에는 암호화 된 메세지의 길이인 정수 N (1 ≤ N ≤ 1000)이 주어진다.
다음 줄에는 암호화 된 메세지가 N개의 16진수 정수로 주어진다. 이 수는 0(10진수) 이상 127(10진수) 이하이다.
7
51 53 51 10 54 54 54
7
53 53 51 54 54 51 10
3. 출력
N개의 문자를 한 줄에 출력한다. 만약 i번째 글자가 문자라면 '-'를, 아니라면 '.'을 출력한다.
---.---
-----.
4. 코드
import sys
input = sys.stdin.readline
n = int(input())
origins = " ."
keys = "0123456789"
# origins과 keys를 아스키코드로 변환 후 16진수로 표현했다.
hex_o, hex_k = origins.encode('ascii').hex(), keys.encode('ascii').hex()
# hex_o와 hex_k를 2자리씩 잘라 배열을 만들었다.
o_list = [int(hex_o[i:i + 2], 16) for i in range(0, len(hex_o), 2)]
k_list = [int(hex_k[i:i + 2], 16) for i in range(0, len(hex_k), 2)]
not_list = []
for i in range(len(origins)):
for j in range(len(keys)):
# xor 연산 후 16진수로 표현했다.
x = str(hex(o_list[i] ^ k_list[j]))
# x를 다시 정수형태로 표현했다.
not_list.append(int(x, 16))
message = list(input().split())
for msg in message:
if int(msg, 16) in not_list:
print('.', end="")
else:
print('-', end="")
5. 풀이설명
① 입력값 n을 입력받는다.
② 공백과 "."으로 이루어진 origins와 0~9로 이루어진 keys를 선언한다.
③ origins와 keys를 아스키코드로 변환 후 16진수로 표현하여 hex_o와 hex_k에 대입한다.
④ hex_o와 hex_k를 2자리씩 잘라 o_list와 h_list 배열을 생성한다.
⑤ 숫자가 아닌 배열 암호키를 넣은 not_list를 빈배열로 선언한다.
⑥ orings와 keys로 중복 for문을 실행하는데 o_list[i]와 k_list[j]를 xor 연산 후 16진수로 변경하여 x에 대입한다.
⑦ x를 다시 정수형으로 변환하여 not_list에 추가한다.
⑧ 입력값 massage를 배열로 입력받는다.
⑨ message로 반복문을 실행하는데 msg를 16진수로 표현한 수가 not_list에 포함되면 . 아니면 -를 결과값으로 출력한다.
6. 느낀점
아스키 코드 변환, 16진수 변환, 배열 자르기 등 해당 문제를 통해 파이썬에서 제공하는 여러 함수를 배우게 되었다.
'알고리즘 > 문제풀이' 카테고리의 다른 글
비트마스킹(캠프 준비 / G5) - 16938 (0) | 2023.07.18 |
---|---|
비트마스킹(시계 / S3) - 2082 (0) | 2023.07.11 |
백트래킹(육각형 우리 속의 개미 / G3) - 17370 (0) | 2023.07.08 |
백트래킹(치킨 배달 / G5) - 15686 (0) | 2023.07.04 |
백트래킹(금공강 사수 / S1) - 27375 (0) | 2023.07.02 |