문제 링크 - https://softeer.ai/practice/6255

 

Softeer - 현대자동차그룹 SW인재확보플랫폼

 

softeer.ai


 

문제 설명

암호화할 문자열(메세지)과 키값이 될 문자열(키)을 2줄에 걸쳐 입력받음

메세지를 아래와 같은 규칙을 적용하여 2글자씩 쌍으로 만듦

- 우선 2자씩 쪼갬 

- 같은 글자로 구성된 쌍은 사이에 'X'를 끼워주는데, 'XX'는 끼워줘봤자 여전히 중복이므로 'Q'를 끼워줌

- 가장 최종적으로 나온 쌍들 중 마지막이 1개 문자로 이루어졌다면 끝에 'X' 추가 (XX가 되어도 무관함)

 

각 쌍에 대해 입력받은 키값을 참고하여 다른 글자로 바꾸어줘야하는데, 참고할 키값은 길이와 상관없이 아래와 같은 규칙으로 5*5의 형태로 변형해야함

- 입력받은 키값을 차례로 돌면서 (0,0)자리부터 한 글자씩 채워줌

- 단, 이미 이전에 등장한 적이 있는 글자가 또 나오면 건너뜀

- 입력받은 키값을 이용해 채웠는데 25자리를 모두 채우지 못 한 경우, 알파벳 중 안 쓴 걸 가져다가 채우면 됨

 

풀이법 구상

문제가 아주 길어서 이해하는데 시간이 좀 걸렸음

문제를 풀어나갈 순서를 아래처럼 정리하면 크게 복잡한 논리를 요구하지는 않아보임

1. 메세지/키 입력받기
2. 2글자 쌍으로 나누기
3. 입력받은 키를 5*5의 형태로 변경
4. 쌍마다 암호화
   (1) 암호판의 같은 행에 존재하는 쌍이면 우측 한 칸씩 밀어서
   (2) 같은 행에 존재하지 않고 같은 열에 존재하면 아래로 한 칸씩 밀어서
   (3) 서로 다른 행/열에 존재하는 경우 서로의 열값을 바꾼 위치로

 

코드 구현 (파이썬 사용)

### 중복되는 글자쌍이 없도록 메세지 수정하는 메소드
def getPair(input):
    # 우선 2자씩 쪼개서 확인
    # 같은 글자로 구성된 쌍은 사이에 'X'를 끼워주는데, 글자쌍이 'XX'인 경우에는 'Q'추가
    # 가장 최종적으로 나온 쌍들 중 마지막이 1개 문자로 이루어졌다면 끝에 'X' 추가 (XX가 되어도 무관함)
    result = input
    while isDuplicated(result): result = setNotDuplicated(result)  # 중복되는 쌍이 없을 때까지 반복
    if len(result)%2 == 1: result += 'X'
    return result

### 중복되는 글자쌍이 존재하는지 확인하는 메소드
def isDuplicated(str):
    for i in range(0,len(str)-1,2):
        if str[i] == str[i+1]: return True
    return False

### 중복되는 글자쌍 사이에 'X' 혹은 'Q'를 추가하는 메소드
def setNotDuplicated(str):
    str_list = list(str)
    for i in range(0,len(str)-1,2):
        if str_list[i] == str_list[i+1]:
            str_list.insert(i+1, 'X' if str_list[i] != 'X' else 'Q')
            return ''.join(str_list)

### 입력된 키값을 기반으로 5*5 크기의 암호판을 만드는 메소드
def getKey(input_key):
    # 입력받은 키값을 차례로 돌면서 (0,0)자리부터 한 글자씩 채워줌
    # 단, 이미 이전에 등장한 적이 있는 글자가 또 나오면 건너뜀
    # 입력받은 키값을 이용해 채웠는데 25자리를 모두 채우지 못 한 경우, 알파벳 중 안 쓴 걸 가져다가 채우면 됨
    alphabet_list = [chr(i) for i in range(ord('A'),ord('Z')+1)]
    alphabet_list.remove('J')
    key_arr = []
    # 우선 입력받은 키값으로 배열 채우기
    for k in input_key:
        if len(key_arr) == 25: break
        if k in alphabet_list:
            key_arr.append(k)
            alphabet_list.remove(k)
    
    # 배열 길이가 25 미만이면 안 쓴 알파벳 사용
    if len(key_arr) < 25:
        for a in alphabet_list:
            if len(key_arr) == 25: break
            key_arr.append(a)

    # 1차원 배열 값을 토대로 2차원 암호판 구성 후 반환
    # result_key = [[0] * 5] * 5 # 얕은 복사로 인해 값 변경에 오류 발생
    result_key = [[0 for p in range(5)] for q in range(5)]
    for p in range(0,5):
        for q in range(0,5): result_key[p][q] = key_arr[(5*p)+q]

    return result_key
            
    

### 수정된 메세지의 글자쌍에 대해 키를 이용하여 암호화하는 메소드
def getResultMsg(pairs, key):
    # case 1) 암호판의 같은 행에 존재하는 쌍이면 우측 한 칸씩 밀어서
    # case 2) 같은 행에 존재하지 않고 같은 열에 존재하면 아래로 한 칸씩 밀어서
    # case 3) 서로 다른 행/열에 존재하는 경우 서로의 열값을 바꾼 위치로
    pair_arr = []
    for i in range(0,len(pairs)-1,2):
        pair_arr.append(pairs[i]+pairs[i+1])

    result = ''
    for pair in pair_arr:
        result += getModifiedKey(pair, key)

    print(result)


def getModifiedKey(pair, key):
    location = [
        [-1, -1],  # 첫번째 글자의 위치
        [-1, -1]   # 두번째 글자의 위치
    ]

    for p in range(0,5):
        for q in range(0,5):
            if pair[0] == key[p][q]: 
                location[0][0] = p 
                location[0][1] = q
            if pair[1] == key[p][q]: 
                location[1][0] = p 
                location[1][1] = q

    if location[0][0] == location[1][0]: 
        # case 1) 암호판의 같은 행에 존재하는 쌍이면 우측 한 칸씩 밀어서
        location[0][1] = (location[0][1] + 1)%5
        location[1][1] = (location[1][1] + 1)%5
        
    elif location[0][1] == location[1][1]: 
        # case 2) 같은 행에 존재하지 않고 같은 열에 존재하면 아래로 한 칸씩 밀어서
        location[0][0] = (location[0][0] + 1)%5
        location[1][0] = (location[1][0] + 1)%5
        
    else: 
        # case 3) 서로 다른 행/열에 존재하는 경우 서로의 열값을 바꾼 위치로
        temp = location[0][1]
        location[0][1] = location[1][1]
        location[1][1] = temp
    
    return (key[location[0][0]][location[0][1]] + key[location[1][0]][location[1][1]])

# 1. 메세지/키 입력받기
msg_input = input()
key_input = input()

# 2. 2글자 쌍으로 나누기
pairs = getPair(msg_input)

# 3. 입력받은 키를 5*5의 형태로 변경
key = getKey(key_input)

# 4. 쌍마다 암호화
getResultMsg(pairs, key)

 

 

이 문제 1시간 안에 풀라 그러면 눈물닦는데 10분은 걸릴 듯;

+ Recent posts