본문 바로가기

Algorithm

SWEA 1240 단순 2진 암호코드 (python)

반응형

1240. [S/W 문제해결 응용] 1일차 - 단순 2진 암호코드 D3

문제

어떤 국가에서는 자국 내 방송국에서 스파이가 활동하는 사실을 알아냈다. 스파이는 영상물에 암호 코드를 삽입하여 송출하고 있었다. 암호 코드는 국가 내 중요 시설을 의미하는 숫자임을 알아냈다. 암호 코드의 규칙은 아래와 같다.

  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. 세로 50. 가로 100 이하의 크기를 가진 직사각형 배열에 암호코드 정보가 포함되어 전달된다. 이 때, 하나의 배열에는 1개의 암호코드가 존재한다. (단, 모든 암호코드가 정상적인 암호코드임을 보장할 수 없다. 비정상적인 암호코드가 포함될 수 있다.) 2. 배열은 1, 0으로 이루어져 있으며 그 안에 포함되어 있는 암호코드 정보를 확인한다. 3. 포함된 암호코드들의 검증코드를 확인하여 정상적인 암호코드인지 확인한다. 4. 정상적인 암호코드들을 판별한 뒤 이 암호코드들에 적혀있는 숫자들의 합을 출력한다. 5. 이때, 총 소요시간이 적을수록 성능이 좋은 것으로 간주된다.

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

  1. 암호코드 하나는 숫자 8개로 구성되며 시작 구분선, 종료 구분선은 별도로 존재하지 않는다. 2. 암호코드가 일부만 표시된 경우는 없다. 모든 암호코드는 8개의 숫자로 구성되어 있다. 3. 암호코드의 세로 길이는 5 ~ 50 칸이다. 4. 암호코드의 가로 길이는 총 길이는 56칸이다. 암호코드에 구성하는 숫자 하나가 차지하는 길이는 7칸이다. 각 숫자들을 그림으로 표시하는 방법은 다음과 같다. img

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

[입력]

가장 첫줄은 전체 테스트 케이스의 수이다.

각 테스트 케이스의 첫 줄에 두 자연수가 주어지는데 각각 배열의 세로 크기 N, 배열의 가로크기 M이다 (1≤N<50, 1≤M<100).

그 다음 N개의 줄에는 M개의 배열의 값이 주어진다.

[출력]

각 테스트 케이스의 답을 순서대로 표준출력으로 출력하며, 각 케이스마다 줄의 시작에 “#C”를 출력하여야 한다.

이때 C는 케이스의 번호이다. 같은 줄에 빈칸을 하나 두고, 입력에 주어진 배열에서 정상적인 암호코드들에 포함된 숫자들의 합을 출력한다.

[예제 풀이]

1번 케이스의 암호코드 정보를 추출하면 아래와 같다.

01110110110001011101101100010110001000110100100110111011
01110110110001011101101100010110001000110100100110111011
01110110110001011101101100010110001000110100100110111011
01110110110001011101101100010110001000110100100110111011
01110110110001011101101100010110001000110100100110111011
01110110110001011101101100010110001000110100100110111011
01110110110001011101101100010110001000110100100110111011

이 숫자가 나타내는 정보는 각각 아래와 같다.
0111011(7) 0110001(5) 0111011(7) 0110001(5) 0110001(5) 0001101(0) 0010011(2) 0111011(7)

검증코드가 맞는지 살펴보면, (7 + 7 + 5 + 2) * 3 + 5 + 5 + 0 + 7 = 80 이므로 올바른 암호코드라고 할 수 있다. 따라서 1번의 출력 값은 38이 된다.

2번 케이스도 같은 방식으로 계산할 경우, 검증코드가 틀렸음을 알 수 있다. 따라서 2번의 출력 값은 0이 된다.

풀이과정

승질머리를 테스트 하는 것 같다...

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

T = int(input())

def find_idx(word):
    for i in range(N):
        for j in range(M-1, 0, -1):
            if info[i][j]:
                line = i
                idx = j
                return line, idx

def change(number):
    dic = {
        '0001101': '0',
        '0011001': '1',
        '0010011': '2',
        '0111101': '3',
        '0100011': '4',
        '0110001': '5',
        '0101111': '6',
        '0111011': '7',
        '0110111': '8',
        '0001011': '9'
    }

    return dic[number]



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

    line = find_idx(info)[0]
    idx = find_idx(info)[1]

    password = info[line][idx-55:idx+1]

    result = ''

    for i in range(0, len(password), 7):
        temp = ''
        for j in range(i, i+7):
            temp += str(password[j])
        result += change(temp)

    odd = 0
    even = 0

    for i in range(7):
        if i % 2:
            even += int(result[i])
        else:
            odd += int(result[i])

    total = odd * 3 + even + int(result[7])

    if total % 10:
        check = 0
    else:
        check = total - int(result[7])

    print("#{} {}".format(tc, check))

근데 알고보니 내가 문제를 잘못 읽은 영향도 있었다....

물론조금씩 틀리긴했는데

복잡해보여도 하나하나 차근차근하면 될문제인데

중간에 길을 잃으면 확인할 길이없어 어려웠다.

풀이

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

T = int(input())

# 암호는 사실 간단하다 몇줄이 있건 간에 1이 나타나는 줄이 유효하고
# 각줄은 다 같으므로 한줄만 검사하면된다.
# 암호는 항상 1로 끝나므로 거꾸로 검사하면서 1이 가장 처음으로 등장하는 인덱스를 찾아보자


# 암호가 시작되는 인덱스를 찾기위한 함수
def find_idx(word):
    for i in range(N):
        for j in range(M-1, 0, -1):
            if info[i][j]:
                line = i
                idx = j
                return line, idx

# 이진숫자를 십진수로 변환해주는 함수이다.
def change(number):
    # 암호 규칙에 따라서 각각의 이진암호와 십진수를 딕셔너리로 정리
    dic = {
        '0001101': '0',
        '0011001': '1',
        '0010011': '2',
        '0111101': '3',
        '0100011': '4',
        '0110001': '5',
        '0101111': '6',
        '0111011': '7',
        '0110111': '8',
        '0001011': '9'
    }
    # 해당되는 밸류값을 리턴해준다.
    return dic[number]



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

    # 함수를 이용해 찾은 인덱스를 다음과 같이 표현해 준다.
    line = find_idx(info)[0]
    idx = find_idx(info)[1]

    # 해당 인덱스를 적용시켜 56자리의 암호를 정리한다.
    password = info[line][idx-55:idx+1]
    # 암호 해독에 성공한 결과갚의 초기값 정의
    result = ''
    # 7단위로 돌면서 검사 - 7자리가 하나의 숫자이기 때문
    for i in range(0, len(password), 7):
        # 7자리 더할 것 초기화
        temp = ''
        # 7자리 내에서 하나씩 더해준다.
        for j in range(i, i+7):
            temp += str(password[j])
        # 더해준 값을 함수를 이용해서 숫자로 변환시켜준다.
        result += change(temp)

    # 홀수자리 숫자와 짝수자리 숫자 초기화
    odd = 0
    even = 0

    # 주의할 점은 인덱스로 들어오기 때문에 홀수가 반대이다.
    # 검증 코드는 포함시키지 않는다.
    for i in range(7):
        # 즉, 인덱스가 홀수일 경우는
        if i % 2:
            # 실제 비밀번호 짝수자리 수 이므로 합을 구해준다.
            even += int(result[i])
        else:
            # 홀수자리를 구해준다.
            odd += int(result[i])
    # 검증을 거쳐야한다.
    check = odd * 3 + even + int(result[7])

    # 검증이 10의 배수가 아니면 0을 
    if check % 10:
        total = 0
    else:
        # 10의 배수이면 각각의 자리수 합을 더해준다.
        total = 0
        for i in range(8):
            total += int(result[i])


    print("#{} {}".format(tc, total))
반응형

'Algorithm' 카테고리의 다른 글

SWEA 5177 이진 힙 (python)  (0) 2021.04.13
SWEA 10729 이진수 표현 (python)  (0) 2021.04.13
SWEA 5186 이진수2 (python)  (0) 2021.04.13
SWEA 5185 이진수 (python)  (0) 2021.04.13
SWEA 5178 노드의 합 (python)  (0) 2021.04.11