본문 바로가기
코딩테스트/백준

[백준/Python] 9046_복호화_Python 풀이

by vulter3653 2022. 4. 9.

https://www.acmicpc.net/problem/9046

 

9046번: 복호화

입력의 T(1 ≤ T ≤ 20)는 테스트 케이스로, 입력 제일 상단에 주어진다. 각각의 테스트 케이스는 한 줄마다 소문자와 공백으로 이루어진 영어 문장이 주어진다. 이 문장의 길이는 적어도 1이상이

www.acmicpc.net

복호화

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
1 초 128MB 1253 576 505 49.172%

문제


암호학에서 치환 암호(substitution cipher)란, 평문에 들어있는 각각의 문자를 주어진 치환 방법으로 암호화하는 방법 중 하나다.

가장 단순한 방법은 평문의 알파벳을 암호문의 알파벳으로 대치시켜 치환시키는 것이다.

예를 들어, 아래와 같은 알파벳 대치표가 주어졌다고 하자.

  • 평문 알파벳 대치표 : abcdefghijklmnopqrstuvwxyz
  • 암호문 알파벳 대치표 : wghuvijxpqrstacdebfklmnoyz

위에 주어진 치환 방법을 통해 암호화하면 평문 "hello there"은 "xvssc kxvbv"가 된다.

한 가지 흥미로운 점은 영어 문법 특성상, 알파벳 'e'가 다른 영문 알파벳에 비해 자주 쓰인다는 것이다.

즉, 암호문 알파벳 대치표 없이 암호문을 복호화하려 할 때, 암호문 알파벳 빈도수를 체크하면 암호문 알파벳 빈도수 중 가장 빈번하게 나타나는 알파벳이 'e'라는 사실을 유추해볼 수 있다.

위 방법으로 암호문 알파벳의 빈도수를 체크하고, 가장 빈번하게 나타나는 문자를 출력하는 프로그램을 작성하면 된다.

만약 주어진 암호문에서 가장 빈번하게 나타나는 문자가 여러 개일 경우, 그 빈번한 문자 중 어느 것이 평문 알파벳 'e'를 가리키는지 확실하게 알 수 없기 때문에 "모르겠음"을 의미하는 '?'를 출력하면 된다.

 

입력


입력의 T(1 ≤ T ≤ 20)는 테스트 케이스로, 입력 제일 상단에 주어진다. 각각의 테스트 케이스는 한 줄마다 소문자와 공백으로 이루어진 영어 문장이 주어진다. 이 문장의 길이는 적어도 1이상이며 255이하다.

 

출력


각각의 테스트 케이스에 대해, 가장 빈번하게 나타나는 문자를 출력하거나 빈번하게 나타나는 문자가 여러 개일 경우 '?'를 출력한다.

 

예제 입력 1


3
asvdge ef ofmdofn
xvssc kxvbv
hull full suua pmlu

 

예제 출력 1


f
v
?

 

풀이


1. 외부에서 Python으로 들어가는 입력값은 문자열 형태로 들어간다. 따라 문자열 형태의 숫자를 정수형으로 변형 시켜, 해당 숫자만큼 for문을 통해 반복하도록 하였다.

 

2. 각각의 테스트 케이스에 대해, 가장 빈번하게 나타나는 문자를 출력하기 위해 Counter 클래스를 통해 (e.g: {(a:3),(b:2)}) dictionary 형태로 저장시켰다.

 

3. 내림차순으로 정리가 되기에 if문을 통해 dictionary의 첫 번 째 빈도수와 두 번 째 빈도수를 비교하여 같을 경우 최빈값을 구할 수 없으므로 '?'가 출력이 되도록, 같지 않을 경우 첫 번째 빈도수가 최빈값이 되므로 첫 번 째 문자가 출력되도록 하였다.

 

4. 문자값의 종류가 하나의 경우, 두 번 째 빈도수를 구할수 없으므로 IndexError가 발생한다. 이 경우에도 정상적으로 작동하기 위해 예외처리 하였다. 

 

from collections import Counter  #Counter 클래스를 사용하기 위해 불러오기

x = int(input())                         #맨 처음에 주어지는 정수값

for x in range(x):                      #주어지는 정수값만큼 횟수를 반복
  y = input()                            #문자값 받기
  y = y.replace(" ","")                  #문자값의 공백 제거
  cnt = Counter(y)                     #Counter 사용해서 각 알파벳과 각 알파벳의 빈도수 dictionary 형태로 저장
  z = cnt.most_common()            #most_common 메서드를 통해 z에 전체요소 저장
  try:                                       #일반적으로 처리될 경우
    if z[0][1] == z[1][1]:                 #빈도값이 첫번째와 두번째가 같을 경우 '?'가 출력
      print('?')
    else:                                     #빈도값이 첫번째와 두번째가 같지 않을 경우 첫번째 빈도값 출력
      print(z[0][0])
 
#주어진 문자 값이 aa 와 같은 경우, 2번째 문자 값이 존재하지 않기에 IndexError 발생
  그렇기에 예외 처리를 통해 정상적으로 작동하도록 만듬
  except:
    print(z[0][0])                           #첫번째 빈도값 출력