SWEA

[SWEA] 1240 : [S/W 문제해결 응용] 1일차 - 단순 2진 암호코드 (Python/파이썬)

sson-coding 2025. 11. 24. 14:56

문제 링크

https://swexpertacademy.com/main/code/problem/problemDetail.do

문제

어떤 국가에서는 자국 내 방송국에서 스파이가 활동하는 사실을 알아냈다. 
스파이는 영상물에 암호 코드를 삽입하여 송출하고 있었는데, 
파이의 암호 코드에 다음과 같은 규칙이 있음을 발견했다.

1. 암호코드는 8개의 숫자로 이루어져 있다.

2. 암호코드에서의 숫자 하나는 7개의 비트로 암호화되어 주어진다. 따라서 암호코드의 가로 길이는 56이다.
   ※ 길이가 56가 아닌 코드는 주어지지 않는다. 주어진 암호코드는 주어진 규칙대로 해독할 수 있음을 보장한다.
      암호코드의 각 숫자가 암호화되는 규칙은 주어진 그림1을 참고하라.

3. 올바른 암호코드는 (홀수 자리의 합 x 3) + (짝수 자리의 합)이 10의 배수가 되어야 한다.
    ex) 암호코드가 88012346일 경우,
    ( ( 8 + 0 + 2 + 4 ) x 3 ) + ( 8 + 1 + 3 + 6) = 60은 10의 배수이므로 올바른 암호코드다.
    ex) 암호코드가 19960409일 경우,
    ( ( 1 + 9 + 0 + 0 ) x 3 ) + ( 9 + 6 + 4 + 9) = 58은 10의 배수가 아니므로 잘못된 암호코드다.


이 암호코드들을 빠르고 정확하게 인식할 수 있는 스캐너를 개발하려고 한다.
스캐너는 암호코드 1개가 포함된 직사각형 배열을 읽는다.
직사각형 배열은 1, 0으로만 이루어져 있고, 암호코드 이외의 부분은 전부 0으로 주어진다.
암호코드 정보가 포함된 2차원 배열을 입력으로 받아 올바른 암호코드인지 판별하는 프로그램을 작성하라.

입력

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

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

그 다음 N개의 줄에 걸쳐 N x M 크기의 직사각형 배열이 주어진다.

출력

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

주어진 암호코드가 올바른 암호코드일 경우, 암호코드에 포함된 숫자의 합을 출력하라. 
만약 잘못된 암호코드일 경우 대신 0을 출력하라.

예제

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

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이 된다.

두 번째 케이스도 같은 방식으로 계산할 경우, 잘못된 암호코드임을 알 수 있다. 따라서 출력 값은 0이 된다.

입력

2
16 80
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000011101101100010111011011000101100010001101001001101110110000000000
00000000000000011101101100010111011011000101100010001101001001101110110000000000
00000000000000011101101100010111011011000101100010001101001001101110110000000000
00000000000000011101101100010111011011000101100010001101001001101110110000000000
00000000000000011101101100010111011011000101100010001101001001101110110000000000
00000000000000011101101100010111011011000101100010001101001001101110110000000000
00000000000000011101101100010111011011000101100010001101001001101110110000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
11 70
00000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
00000001100101000110100011010111101101110010011001001101110110000000000
00000001100101000110100011010111101101110010011001001101110110000000000
00000001100101000110100011010111101101110010011001001101110110000000000
00000001100101000110100011010111101101110010011001001101110110000000000
00000001100101000110100011010111101101110010011001001101110110000000000
00000001100101000110100011010111101101110010011001001101110110000000000
00000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000

출력

#1 38
#2 0

정답 및 풀이

t = int(input())

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

for tc in range(1, t+1):
    n, m = map(int, input().split())
    arr = [input().strip() for _ in range(n)]

    line = ""
    for row in arr:
        if "1" in row:
            line = row

    end = line.rfind("1")
    start = end - 55

    pwd = []
    for i in range(0, 56, 7):
        bit = line[start + i : start + i + 7]
        pwd.append(code_map[bit])

    odd_sum = pwd[0] + pwd[2] + pwd[4] + pwd[6]
    even_sum = pwd[1] + pwd[3] + pwd[5]

    valid = (odd_sum * 3 + even_sum + pwd[7]) % 10

    if valid == 0:
        print(f"#{tc} {sum(pwd)}")
    else:
        print(f"#{tc} 0")
  1. t = int(input())
    • 테스트 케이스 개수를 입력받는다.
  2. code_map = { ... }
    • 7자리 이진코드를 실제 숫자로 매핑하는 표를 미리 딕셔너리 형태로 만든다.
  3. for tc in range(1, t+1):
    • 테스트 케이스 번호를 1부터 시작하여 반복한다.
  4. n, m = map(int, input().split())
    • 바코드 배열의 크기(n행, m열)를 입력받는다.
  5. arr = [input().strip() for _ in range(n)]
    • 전체 배열을 문자열 형태로 n줄 입력받는다.
  6. line = ""
    • 바코드가 포함된 라인을 저장할 변수를 초기화한다.
  7. for row in arr:
    • 각 행을 순회한다.
  8. if "1" in row:
    • 해당 행에 1이 포함되어 있으면, 그 행이 바코드가 있는 줄이므로 저장한다.
  9. line = row
    • 바코드가 포함된 마지막 행을 line에 저장한다.
    • SWEA 의 특징상 마지막 1이 있는 행이 바코드가 있는 행이다.
  10. end = line.rfind("1")
    • 바코드의 맨 오른쪽 끝(마지막 1의 위치)을 찾는다.
  11. start = end - 55
    • 바코드 전체 길이가 56이므로 시작점은 55만큼 왼쪽으로 이동한 위치이다.
  12. pwd = []
    • 디코딩한 숫자 8개를 저장할 리스트이다.
  13. for i in range(0, 56, 7):
    • 바코드는 7비트씩 총 8개 구간으로 구성되므로 7칸씩 이동하면서 반복한다.
  14. bit = line[start + i : start + i + 7]
    • 해당 7자리 비트를 잘라온다.
  15. pwd.append(code_map[bit])
    • 잘라온 7자리 비트를 숫자로 변환하여 비밀번호 리스트에 추가한다.
  16. odd_sum = pwd[0] + pwd[2] + pwd[4] + pwd[6]
    • 홀수 자리(0,2,4,6번째)의 숫자 합을 구한다.
  17. even_sum = pwd[1] + pwd[3] + pwd[5]
    • 짝수 자리(1,3,5번째)의 숫자 합을 구한다.
  18. valid = (odd_sum * 3 + even_sum + pwd[7]) % 10
    • 문제에서 제시한 검증식으로 유효성 검사를 수행한다.
  19. if valid == 0:
    • 나머지가 0이면 바코드가 정상이다.
  20. print(f"#{tc} {sum(pwd)}")
    • 인증 성공 시 8개 숫자의 합을 출력한다.
  21. else:
    • 인증 실패한 경우.
  22. print(f"#{tc} 0")
    • 유효하지 않으면 0을 출력한다.

새롭게 배운 내용 및 느낀점

  • rfind()
    • 문자열에서 오른쪽부터 찾기 시작해서 찾고자 하는 문자가 가장 마지막에 등장하는 위치를 반환하는 함수
    • 문자열.rfind(찾을문자)