@@@ 알고리즘/백준 스터디

백준 2892(심심한 준규) - 해결

HTG 2022. 1. 7. 03:43
728x90

심심한 준규

 

문제

해빈이는 준규에게 메세지를 받았다. 준규는 세계 최고 수준의 암호학자이기 때문에 해빈이에게 암호로 메세지를 보낸다. 이번에 준규는 One Time Pad(OTP) 암호화 방식을 사용하기로 했다. 준규는 OTP방식을 제대로 적용하면 절대 해독할 수 없다는 것을 알기 때문에, 해빈이가 해석할 수 있도록 몇 가지 힌트를 같이 보내기로 했다.

준규는 메세지에 항상 영소문자, 온점('.'), 공백 (' ', ASCII코드 32)만 쓴다. 그리고 key값으로는 항상 '0'부터 '9'까지의 숫자만 쓴다. 이 사실을 알고 있는 해빈이는 이를 이용해 메세지에 있는 온점과 공백의 위치를 알 수 있다는 것을 깨닫고, 당신에게 프로그램으로 만들어달라고 부탁했다.

준규가 이런 메세지를 보낸 게 한두 번이 아니기 때문에 해빈이는 OTP 암호화 방식을 알고 있다. 예를 들어 "0120123"을 key로 사용해서 "abc efg"라는 문자열을 암호화하면 아래와 같다.

 

abc efg
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 연산한다. 그 결과가 암호화 된 메세지이다.

 

입력

입력에 첫 줄에는 암호화 된 메세지의 길이인 정수 N (1 ≤ N ≤ 1000)이 주어진다.

다음 줄에는 암호화 된 메세지가 N개의 16진수 정수로 주어진다. 이 수는 0(10진수) 이상 127(10진수) 이하이다.

 

출력

N개의 문자를 한 줄에 출력한다. 만약 i번째 글자가 문자라면 '-'를, 아니라면 '.'을 출력한다.


처음에는 무슨 문제인가 하였다.

그런데 " "과 . 만 구분해내면 되는 문제였다.

a~z까지의 아스키 코드가 97~127이고 " "가 32, . 이 46 이기 때문에 차이가 많이 나고 

이를 각각 "0" ~ "9" 의 아스키 코드인 48 ~ 57와 XOR 연산을 해봤을 때 64를 기준으로 나뉘어서 처음에 이런 방식으로 하였다.

그 다음 만약 아스키 코드를 모른다는 가정하에 하는 방식도 하였다.

그 방식은 인코딩된 메세지의 각 원소를 10진수로 바꾸고 이를 "0" ~ "9" 에 해당하는 아스키코드인 48~57까지 XOR 연산했을 때 이는 디코딩 과정이 되고 디코딩 결과가 " ", . 에 해당하는 32와 46이 나온다면 그 원소는 " "나 . 에 해당한다고 할 수 있다. 

 

import sys
input = sys.stdin.readline

N = int(input().strip())
enco_message = list(input().split())

#### 1번째 방법
for i in range(N):
    if int(enco_message[i],16) >= 64:
        print('-',end='')
    else:
        print('.',end='')


#### 2번째 방법
for i in range(N):
    # 인코딩 메세지 원소를 10진수로 변환
    num = int(enco_message[i],16)
    # 48~57까지 XOR 연산하여 디코딩 과정을 거침
    # 인코딩할때 XOR을 했기때문에 다시해주면 디코딩 과정이 된다.
    for key in range(ord('0'),ord('9')+1):
        dec_num = num ^ key
        # 디코딩 결과가 ' ', . 에 해당하는 아스키코드와 같다면 
        # 해당 메세지 원소는 문자가 아니기 때문에 .를 출력하고 다음
        if dec_num == ord(' ') or dec_num == ord('.'):
            print('.',end='')
            break
    # 만약 "0" ~ "9" 까지 다 했는데 해당하지 않는다면
    # 문자라고 할 수 있다.
    else:
        print('-',end='')
# . 과 "0" ~ "9" XOR 연산
print(46^30,46^31,46^32,46^33,46^34,46^35,46^36,46^37,46^38,46^39)
# ' ' 과 "0" ~ "9" XOR 연산
print(32^30,32^31,32^32,32^33,32^34,32^35,32^36,32^37,32^38,32^39)

# a~z 와 "0" ~ "9" XOR 연산
for i in range(97,123):
    for j in range(30,40):
        print(i^j,end = ' ')
    print()

# 64를 기준으로 나뉜다.
'''
48 49 14 15 12 13 10 11 8 9
62 63 0 1 2 3 4 5 6 7
127 126 65 64 67 66 69 68 71 70
124 125 66 67 64 65 70 71 68 69
125 124 67 66 65 64 71 70 69 68 
122 123 68 69 70 71 64 65 66 67
123 122 69 68 71 70 65 64 67 66 
120 121 70 71 68 69 66 67 64 65 
121 120 71 70 69 68 67 66 65 64 
118 119 72 73 74 75 76 77 78 79 
119 118 73 72 75 74 77 76 79 78 
116 117 74 75 72 73 78 79 76 77 
117 116 75 74 73 72 79 78 77 76 
114 115 76 77 78 79 72 73 74 75 
115 114 77 76 79 78 73 72 75 74
112 113 78 79 76 77 74 75 72 73
113 112 79 78 77 76 75 74 73 72
110 111 80 81 82 83 84 85 86 87 
111 110 81 80 83 82 85 84 87 86 
108 109 82 83 80 81 86 87 84 85
109 108 83 82 81 80 87 86 85 84
106 107 84 85 86 87 80 81 82 83
107 106 85 84 87 86 81 80 83 82
104 105 86 87 84 85 82 83 80 81
105 104 87 86 85 84 83 82 81 80
102 103 88 89 90 91 92 93 94 95 
103 102 89 88 91 90 93 92 95 94
100 101 90 91 88 89 94 95 92 93
'''