[Softeer] S804 플레이페어 암호
[Softeer]
Question
Language: Python
해당 문제는 주어진 문제의 조건에 따라 구현하면되는 비교적 간단한 유형의 문제이다.
주어진 평문에 대해 암호화를 수행하는 것이 문제의 목표인데, 암호화는 크게 3가지 단계로 구성된다.
- 키맵의 구성
주어진 key를 5*5 형태의 행렬 형태로 변환하는 작업을 수행한다. alpha_location이라는 dictionary을 통해 각각의 문자의 row,col 위치를 저장하고, key_map이라는 이차원 배열을 통해 각각 row,col 별로 문자를 저장한다. 이렇게 2개의 저장구조를 활용하여 row,col -> 문자, 문자 -> row,col을 빠르게 할 수 있도록 한다.
def next_location(row,col):
col+=1
if col==5:
row+=1
col=0
return row,col
#알파벳 채우기
alpha_locations={chr(index):(-1,-1) for index in range(ord("A"),ord("A")+26) if index != ord("J")}
key_matrix=[[""] *5 for _ in range(5)]
row,col=0,0
#key에 대한 맵핑 수행
for char in cipher_key:
#이미 입력된 알파벳이면 넘어간다.
if alpha_locations[char] !=(-1,-1):
continue
alpha_locations[char]=(row,col)
key_matrix[row][col]=char
row,col=next_location(row,col)
#key에 없는 나머지 알파벳에 대한 맵핑
for key in alpha_locations:
#이미 입력된 알파벳이면 넘어간다.
if alpha_locations[key] != (-1,-1):
continue
alpha_locations[key]=(row,col)
key_matrix[row][col]=key
row,col=next_location(row,col)
- 두 쌍씩 분리
평문을 두 문자씩 묶어서 쌍을 만드는 작업을 수행한다.
pairs=[]
length=len(plain)
index=0
while index < length:
#마지막에 하나의 인덱스만 남는 경우
if index==length-1:
pairs.append(plain[index]+"X")
break
#연속된 문자가 서로 같은 경우 X,Q를 삽입한다.
if plain[index]==plain[index+1]:
if plain[index]=="X":
pairs.append(plain[index]+"Q")
else:
pairs.append(plain[index]+"X")
index+=1
#그외의 경우 서로 붙여서 쌍을 만든다.
else:
pairs.append(plain[index]+plain[index+1])
index+=2
- 암호화
분리된 문자쌍에 대해 key_map, alpha_locations을 이용하여 암호화를 수행한다.
#암호화 수행
for pair in pairs:
pair1_row,pair1_col=alpha_locations[pair[0]]
pair2_row,pair2_col=alpha_locations[pair[1]]
cipher1,cipher2="",""
#행이 같은 경우
if pair1_row==pair2_row:
cipher1=key_matrix[pair1_row][(pair1_col+1)%5]
cipher2=key_matrix[pair1_row][(pair2_col+1)%5]
#열이 같은 경우
elif pair1_col==pair2_col:
cipher1=key_matrix[(pair1_row+1)%5][pair1_col]
cipher2=key_matrix[(pair2_row+1)%5][pair1_col]
#그 외
else:
cipher1=key_matrix[pair1_row][pair2_col]
cipher2=key_matrix[pair2_row][pair1_col]
cipher_text+=(cipher1+cipher2)
Solution
import sys
def next_location(row,col):
col+=1
if col==5:
row+=1
col=0
return row,col
def solution():
#알파벳 채우기
alpha_locations={chr(index):(-1,-1) for index in range(ord("A"),ord("A")+26) if index != ord("J")}
key_matrix=[[""] *5 for _ in range(5)]
row,col=0,0
#key에 대한 맵핑 수행
for char in cipher_key:
#이미 입력된 알파벳이면 넘어간다.
if alpha_locations[char] !=(-1,-1):
continue
alpha_locations[char]=(row,col)
key_matrix[row][col]=char
row,col=next_location(row,col)
#key에 없는 나머지 알파벳에 대한 맵핑
for key in alpha_locations:
#이미 입력된 알파벳이면 넘어간다.
if alpha_locations[key] != (-1,-1):
continue
alpha_locations[key]=(row,col)
key_matrix[row][col]=key
row,col=next_location(row,col)
#두쌍씩 분해
pairs=[]
length=len(plain)
index=0
while index < length:
#마지막에 하나의 인덱스만 남는 경우
if index==length-1:
pairs.append(plain[index]+"X")
break
#연속된 문자가 서로 같은 경우 X,Q를 삽입한다.
if plain[index]==plain[index+1]:
if plain[index]=="X":
pairs.append(plain[index]+"Q")
else:
pairs.append(plain[index]+"X")
index+=1
#그외의 경우 서로 붙여서 쌍을 만든다.
else:
pairs.append(plain[index]+plain[index+1])
index+=2
cipher_text=""
#암호화 수행
for pair in pairs:
pair1_row,pair1_col=alpha_locations[pair[0]]
pair2_row,pair2_col=alpha_locations[pair[1]]
cipher1,cipher2="",""
#행이 같은 경우
if pair1_row==pair2_row:
cipher1=key_matrix[pair1_row][(pair1_col+1)%5]
cipher2=key_matrix[pair1_row][(pair2_col+1)%5]
#열이 같은 경우
elif pair1_col==pair2_col:
cipher1=key_matrix[(pair1_row+1)%5][pair1_col]
cipher2=key_matrix[(pair2_row+1)%5][pair1_col]
#그 외
else:
cipher1=key_matrix[pair1_row][pair2_col]
cipher2=key_matrix[pair2_row][pair1_col]
cipher_text+=(cipher1+cipher2)
print(cipher_text)
if __name__ == "__main__":
plain=str(sys.stdin.readline().strip())
cipher_key=str(sys.stdin.readline().strip())
solution()
댓글남기기