practivceAlgorithm/다시 봐야할 문제들

[SWEA][Python] 1242 암호코드스캔

findTheValue 2021. 9. 30. 17:01

 

암호문에서 16진수로 표현된 바코드를 찾아 2진수로 변환, decode 규칙에 따라 해석한 10진수가 암호의 조건에 맞으면 암호값을 산출하는 문제입니다.

 

input값을 정제하는 것부터 매우 어려웠습니다.

결국 핵심은 2진수 값을 구하면 0,1,0,1의 비율을 찾아 매칭시키는 것 입니다.

웃긴건 112자리 안에 56자리 암호가 숨어있을수도 있으니 조심하시면 됩니다.

 

 

import sys
sys.stdin = open('input.txt')


# 알파뱃이면 10 + 그 번호 즉 16진수를 10진수로 치환하는 함수.
def get_val(ch):
    val = (ord(ch) - ord('A')) + 10 if ord(ch) > ord('9') else ord(ch) - ord('0')
    return val


# 남의 코드
def find():
    ret = 0
    for i in range(N):
        j = M - 1
        # 뒤부터 순회해서 0이 아니고 뒤가 0인 즉 암호의 마지막 숫자를 찾으면?
        while j >= 0:
            if arr[i][j] != '0' and arr[i - 1][j] == '0':
                pwd = []
                min_val = 0
                # 만난 16진수를 10진수로 바꾼 val 값
                val, c = get_val(arr[i][j]), 0
                # 8자리의 암호를 찾을 것임.
                for k in range(8):
                    c2 = c3 = c4 = 0
                    # val 의 2진표기에서 '0'을 check 하는 반복문 뒤에있는 0은 배제하여 세어주지 않습니다.
                    while (val & 1) == 0:
                        val, c = val >> 1, c + 1
                        # 길이 4개를 측정하면 앞쪽 16진수로 넘어갑니다. 그전에 1이 나오면 종료합니다.
                        if c == 4:
                            j, c = j - 1, 0
                            val = get_val(arr[i][j])
                    # 여기서부터 2진수의 시작입니다. 1의 갯수를 세줍니다.
                    while val & 1:
                        val, c, c4 = val >> 1, c + 1, c4 + 1
                        if c == 4:
                            j, c = j - 1, 0
                            val = get_val(arr[i][j])
                    # 0의 갯수를 세줍니다.
                    while (val & 1) == 0:
                        val, c, c3 = val >> 1, c + 1, c3 + 1
                        if c == 4:
                            j, c = j - 1, 0
                            val = get_val(arr[i][j])
                    # 1의 갯수를 세줍니다.
                    while val & 1:
                        val, c, c2 = val >> 1, c + 1, c2 + 1
                        if c == 4:
                            j, c = j - 1, 0
                            val = get_val(arr[i][j])
                    # 마지막 순회까지 반복하면 56 혹은 112개의 탐색이 끝납니다.
                    if k == 0:
                        # 최소단위는 1 or 2가 될것입니다. 56이면 1, 112이면 2
                        min_val = min(c2, c3, c4)

                    # 단위로 나누어 비율에 따라 decode 된 숫자를 가져와 pwd 에 저장합니다.
                    pwd.append(P[(c2 // min_val, c3 // min_val, c4 // min_val)])

                # 홀, 짝
                a = pwd[0] + pwd[2] + pwd[4] + pwd[6]
                b = pwd[1] + pwd[3] + pwd[5] + pwd[7]
                # 조건에 맞으면 ret 값에 더해줍니다.
                if ((b * 3 + a) % 10) == 0:
                    ret += (a + b)
            j -= 1
    return ret


P = {(2, 1, 1): 0,
     (2, 2, 1): 1,
     (1, 2, 2): 2,
     (4, 1, 1): 3,
     (1, 3, 2): 4,
     (2, 3, 1): 5,
     (1, 1, 4): 6,
     (3, 1, 2): 7,
     (2, 1, 3): 8,
     (1, 1, 2): 9}

T = int(input())
for tc in range(1, T + 1):
    N, M = map(int, input().split())
    arr = [input() for _ in range(N)]

    print(f'#{tc} {find()}')