SWEA_1240_단순 2진 암호코드

김병훈·2021년 4월 13일
0

내 코드

import sys

sys.stdin = open("단순 2진 암호코드.txt")

# 패턴이 키 값이 되는 형태
pattern_dic = {
    "0001101": 0,
    "0011001": 1,
    "0010011": 2,
    "0111101": 3,
    "0100011": 4,
    "0110001": 5,
    "0101111": 6,
    "0111011": 7,
    "0110111": 8,
    "0001011": 9,
}

T = int(input())

for tc in range(1, T + 1):
    # N: 배열의 세로 크기
    # M: 배열의 가로 크기
    N, M = map(int, input().split())
    ARR = [input() for _ in range(N)]

    # 배열을 탐색하며 1이 있는지 확인합니다.
    start_r = -1
    for i in range(N):
        if "1" in ARR[i]:
            start_r = i
            break
    # 7줄만 남기고 배열을 잘라내자
    ARR = ARR[start_r:start_r + 7]
    # 열 잘라내기
    # 뒤에서부터 탐색
    end_c = M
    for i in range(M - 1, -1, -1):
        # 모든 암호가 1로 끝나기 때문에, 맨 뒤를 확인한다.
        if ARR[0][i] == "1":
            end_c = i
            break
    # 우리가 찾아야 탐색해야 할 문자열
    secret_text = ARR[0][end_c - 55:end_c + 1]

    solve_list = []
    for i in range(0, 56, 7):
        temp_secret = secret_text[i:i + 7]
        solve_list.append(pattern_dic[temp_secret])

    # 검증 과정
    confirm_number = 0
    for i in range(8):
        if (i + 1) % 2:
            confirm_number += int(solve_list[i]) * 3
        else:
            confirm_number += int(solve_list[i])

    # 검증 실패 시 0 출력
    result = 0
    if confirm_number % 10 == 0:
        result = sum(solve_list)

    print(f"#{tc} {result}")

접근 방식

  1. 암호 패턴에 해당하는 값을 대응시키기 위해 딕셔너리를 선언하였다.

    키값으로 암호 문자열을 두어도 되고, 해독한 숫자로 해도 될 것 같지만 이 문제는 암호화 된 것을 풀어내는 과정으로 진행되고 있기 때문에 암호 패턴을 키값으로 설정하였다.

  1. 필요 없는 문자열은 잘라주었다.

    • 동일한 암호 문자열이 몇 개의 행에 걸쳐 존재하는데, 해독을 위해서는 한 줄만 알아도 되기 때문에 암호 문자열에만 포함된 1을 찾아 해당 행만 남겨주었다.

    • 암호 패턴이 0으로 시작하기 때문에, 앞에서부터 찾는 것은 다소 어려울 수 있다는 생각이 들었다.

      살펴보니 모든 암호 패턴은 1로 끝나는 것을 확인할 수 있었고, 잘라낸 행을 뒤에서부터 탐색하여 1을 찾는 것으로 실제 암호 패턴의 위치를 찾을 수 있었다.


다른 멋진 분들의 코드 살펴보기

decryption = {
    '0001101': 0,
    '0011001': 1,
    '0010011': 2,
    '0111101': 3,
    '0100011': 4,
    '0110001': 5,
    '0101111': 6,
    '0111011': 7,
    '0110111': 8,
    '0001011': 9
}

T = int(input())

for tc in range(1, T + 1):
    N, M = map(int, input().split())
    arr = [input() for _ in range(N)]
    code = ''
    for i in range(N):
        for j in range(M -1, -1, -1):
            if arr[i][j] == '1':
                code += arr[i][j - 55 : j + 1]
    dcode= []
    start, end = 0, 7
    for i in range(8):
        dcode.append(decryption[code[start:end]])
        start += 7
        end += 7
 
    if ((dcode[0] + dcode[2] + dcode[4] + dcode[6]) * 3 + dcode[1] + dcode[3] + dcode[5] + dcode[7]) % 10 == 0:
        print('#{} {}'.format(tc, sum(dcode)))
    else:
        print('#{} {}'.format(tc, 0))
  • 이번 코드를 작성하면서 변수명을 뭐라고 해야 하나 계속 고민을 했었는데, 이 코드에서 답을 찾았다.
    code - decode - decryption
    이렇게 변수를 선언하니 한층 더 확인하기 쉬워진다.
  • 암호 패턴의 위치(열)를 찾기 위해 뒤에서부터 탐색한 것을 확인할 수 있다.

T = int(input())

number = [
[0,0,0,1,1,0,1],
[0,0,1,1,0,0,1],
[0,0,1,0,0,1,1],
[0,1,1,1,1,0,1],
[0,1,0,0,0,1,1],
[0,1,1,0,0,0,1],
[0,1,0,1,1,1,1],
[0,1,1,1,0,1,1],
[0,1,1,0,1,1,1],
[0,0,0,1,0,1,1]
]
 
 
for tc in range(1,T+1):
    N, M = map(int, input().split())
    arr = []
    # 행을 받아와서 1이 있는 행의 인덱스값 추출
    for i in range(N):
        arr += [list(map(int, ' '.join(input()).split()))]
        if 1 in arr[i]:
            ob_i = i
 
    # 사용할 행만 따로 뽑기
    data = list(arr[ob_i])
 
    # 역순으로 방문하여 1이되는 열 인덱스 파악
    for i in range(M-1,-1,-1):
        if data[i] == 1:
            ob_i = i
            break
 
 
    # 숫자 섹션을 나누어서 암호숫자와 대비, 숫자 찾기
    num_res = []
    data = data[ob_i-55:ob_i+1] # 해당 인덱스 추출
    for i in range(0,56,7):
        section = data[i:i+7] # 섹션 뽑기
        for j in range(len(number)): # 암호숫자 비교
            cnt = 0
            for k in range(7):
                if section[k] == number[j][k]:
                    cnt += 1
            if cnt == 7: # 완전히 일치하면 저장
                num_res += [j]
                break
 
    # 암호 유효성 판별
    temp1 = 0 # 홀수자리 합
    temp2 = 0 # 짝수자리 합
    for i in range(7):
        if i % 2:
            temp2 += num_res[i]
        else:
            temp1 += num_res[i]
    if (temp1*3+temp2+num_res[7]) % 10 or not (temp1+temp2+num_res[7]):
        res = 0
    else:
        res = temp1+temp2+num_res[7]
    print('#{} {}'.format(tc,res))
  • 역순으로 열을 탐색하는 방법이 동일

  • 암호 패턴 해석을 위해 이중배열을 선언한 것에서 차이를 발견할 수 있었다.
    배열로 선언하다보니 암호숫자를 비교하는 과정에서 반복문이 여러번 사용되고 있는데, 개인적으로는 딕셔너리로 접근하는 것이 깔끔하다고 생각하지만 어느것이 우월하다 할 필요는 없을 듯 하다.

profile
재밌는 걸 만드는 것을 좋아하는 메이커

0개의 댓글