SW Expert

[SWEA] 1242 암호코드 스캔 Python

꿀떡최고 2021. 5. 6. 10:46
반응형

[ 문제 ]

 

난이도:  D5

문제 번호:  1242

 

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV15JEKKAM8CFAYD&categoryId=AV15JEKKAM8CFAYD&categoryType=CODE&problemTitle=1242&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

swexpertacademy.com


 

어떤 국가에서는 자국 내 방송국에서 스파이가 활동하는 사실을 알아냈다.

스파이는 영상물에 암호 코드를 삽입하여 송출하고 있었다.

암호 코드는 국가 내 중요 시설을 의미하는 숫자임을 알아냈다. 암호 코드의 규칙은 아래와 같다.

 

1. 총 8개의 숫자로 이루어져 있다.

2. 앞 7자리는 상품 고유의 번호를 나타내며, 마지막 자리는 검증 코드를 나타낸다.

    - 검증코드는 아래와 같은 방법으로 계산한다.

    “(홀수 자리의 합 x 3) + 짝수 자리의 합 + 검증 코드” 가 10의 배수가 되어야 한다.

    상품 고유의 번호가 8801234일 경우,

    “( ( 8 + 0 + 2 + 4 ) x 3 ) + ( 8 + 1 + 3 ) + 검증 코드”

    = “42 + 12 + 검증 코드”

    = “54 + 검증 코드” 가 10 의 배수가 되어야 하므로, 검증코드는 6이 되어야 한다.

    즉, 88012346 이 정상적인 암호코드고, 그 외의 검증코드가 포함된 경우 비정상적인 암호코드다.



A 업체에서는 이 암호코드들을 빠르고 정확하게 인식할 수 있는 스캐너를 개발하려고 한다.

스캐너의 성능은 아래와 같은 방법으로 측정된다.
 

1. 세로 2000. 가로 500 이하의 크기를 가진 직사각형 배열에 암호코드 정보가 포함되어 전달된다. 이 때, 하나의 배열에는 1개 이상의 암호코드가 존재한다. (단, 모든 암호코드가 정상적인 암호코드임을 보장할 수 없다. 비정상적인 암호코드가 포함될 수 있다.)

2. 배열은 16진수로 이루어져 있으며, 이 배열을 2진수로 변환하여 그 안에 포함되어 있는 암호코드 정보를 확인한다.

3. 포함된 암호코드들의 검증코드를 확인하여 정상적인 암호코드인지 확인한다.

4. 정상적인 암호코드들을 판별한 뒤 이 암호코드들에 적혀있는 숫자들의 합을 출력한다.

5. 이때, 총 소요시간이 적을수록 성능이 좋은 것으로 간주된다.



배열에 포함되어 있는 암호코드의 세부 규칙은 아래와 같다.
 

1. 암호코드 하나는 숫자 8개로 구성되며 시작 구분선, 종료 구분선은 별도로 존재하지 않는다.

2. 암호코드들이 붙어있는 경우는 존재하지 않는다. (각 암호코드의 둘레에는 최소 1칸 이상의 빈 공간이 존재한다.)

3. 암호코드가 일부만 표시된 경우는 없다. 모든 암호코드는 8개의 숫자로 구성되어 있다.

4. 암호코드의 세로 길이는 5 ~ 100 칸이다.

5. 암호코드의 가로 길이는 암호코드 선의 두께에 따라 달라지며, 두께가 가장 가는 경우, 숫자 하나가 차지하는 길이는 7칸 이다. 각 숫자들을 그림으로 표시하는 방법은 다음과 같다.

 

각 숫자는 흰색과 파란색의 넓이 비로 표현된다.

암호코드의 가로 길이가 길어질 경우,

숫자 하나가 차지하는 길이는 7의 배수가 된다.

예를 들어, 가로 길이가 2배가 될 경우 9는 아래와 같이 표시될 수 있다.

 

6. 암호코드 하나의 최소 가로 길이는 56이며, 암호코드 선이 굵어질 경우, 56의 배수의 길이를 갖게 된다. 예를 들어 암호코드 숫자 하나가 14칸을 사용하는 경우, 암호코드 하나의 가로길이는 112가 된다. 암호코드 하나에 포함되는 암호코드 숫자들은 모두 동일한 크기를 갖는다.


암호코드 정보가 포함된 2차원 배열을 입력으로 받아 정상적인 암호코드를 판별하는 프로그램을 작성하라.


 

[ 코드 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
change_bi = {'0''0000''1''0001''2''0010''3''0011''4''0100''5''0101''6''0110''7''0111''8''1000''9''1001',
              'A''1010''B''1011''C''1100''D''1101''E''1110''F''1111'}
 
code = {(211): 0,
        (221): 1,
        (122): 2,
        (411): 3,
        (132): 4,
        (231): 5,
        (114): 6,
        (312): 7,
        (213): 8,
        (112): 9}
 
for tc in range(1int(input())+1):
    N, M = map(int, input().split())
    # 중복 제거하고 0만 있는 배열 제거
    numbers = sorted(list(set([input()[:M] for _ in range(N)])))
    final = 0
    visited = []
    numbers.pop(0)
 
    # 이진수
    for j in range(len(numbers)):
        change = ''
        for n in range(len(numbers[j])):
            change += change_bi[numbers[j][n]]
        change = change.rstrip("0")
 
        decimal_num_li = []
        # 0과 1 카운트 해서 비율로 숫자 찾기
        n1 = n2 = n3 = n4 = 0
        for i in range(len(change)-1-1-1):
            if change[i] == '1' and n3 == 0:
                n4 += 1
            elif change[i] == '0' and n2 == 0:
                n3 += 1
            elif change[i] == '1' and n1 == 0:
                n2 += 1
            elif change[i] == '0':
                if change[i-1== '1':
                    n = min(n2, n3, n4)
                    decimal_num_li.append((code[n2//n, n3//n, n4//n]))
                    n2 = n3 = n4 = 0
                    if len(decimal_num_li) == 8:
                        if not ((decimal_num_li[1+ decimal_num_li[3+ decimal_num_li[5+ decimal_num_li[7])*3 + decimal_num_li[0+ decimal_num_li[2+ decimal_num_li[4+ decimal_num_li[6]) % 10:
                            if decimal_num_li not in visited:
                                final += sum(decimal_num_li)
                                visited.append(decimal_num_li)
                        decimal_num_li = []
    print('#{} {}'.format(tc, final))
cs
반응형