[SWEA] 1242. [S/Wトラブルシューティングアプリケーション]1日目-スキャンパスワード[D 5]


📚 質問する


https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV15JEKKAM8CFAYD&categoryId=AV15JEKKAM8CFAYD&categoryType=CODE&problemTitle=%EC%95%94%ED%98%B8%EC%BD%94%EB%93%9C+%EC%8A%A4%EC%BA%94&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1
これはシステム解決が必要な体現問題である.
そこで,それを関数としてモジュール化して解く.
入力したコードは16進数で入力します.
複数行入力重複除外後、リストとして受信しsetデータ型に設定し、リストに再変換します.ここで順番は大丈夫です.そうしてもいいです.
次に右端で0を除去します.コードの右端は1で始まる必要があるからです.
コードの幅が異なる場合があります.コード幅が一番薄い時は重複していない時なので56です.
繰り返しがあれば、数字は繰り返し、56の倍数に入ります.
最後の数字は7つの組成[0,1,0,1]の組合せから7つである.
そこで,1から入ってきてcntを数え,4回まで数える.
個数は7個幅は1個,14個幅は2個である.
最初に1を入力すると、値を覚えて復号します.
復号化については、次の項目を参照してください.

📌 単純バイナリパスワード


https://velog.io/@yunhlim/SWEA-1240.-SW-%EB%AC%B8%EC%A0%9C%ED%95%B4%EA%B2%B0-%EC%9D%91%EC%9A%A9-1%EC%9D%BC%EC%B0%A8-%EB%8B%A8%EC%88%9C-2%EC%A7%84-%EC%95%94%ED%98%B8%EC%BD%94%EB%93%9C-D3
1行に複数のコードがある可能性があるため、パスワードを0に変更し、右側の0を再度削除し、次のコードを確認します.
この手順を繰り返し、通常のパスワードの結果を加算して出力します.

📒 コード#コード#

def ten_to_binary(n):  # 10진수를 2진수로 변환
    ans = ''
    for i in range(4):  # 4자리
        ans = str(n % 2) + ans  # 나머지를 왼쪽에 붙여준다.
        n //= 2
    return ans


def hex_to_binary(n):
    ans = ''
    for c in n:  # 입력받은 16진수 순회
        if c.isdigit():  # 숫자인 경우
            ans += ten_to_binary(int(c))
        else:  # 문자인 경우 딕셔너리 활용
            ans += ten_to_binary(hex_c[c])
    return ans


def search_code():      # 메인 함수, 총 암호 해독 값의 합을 찾는다.
    total = 0
    for i in range(len(arr)):   # 줄 별로 확인
        arr[i] = hex_to_binary(arr[i])
        while arr[i]:    # ''만 남으면 보지않는다.
            e, width = code_status(i)       # 코드의 너비와 끝점을 받아온다.
            binary = arr[i][e - 56 * width + 1:e + 1: width]    # 코드 길이로 자르기
            if binary not in visited:    # 중복된 코드가 있으면 보지 않는다.
                total += solve_code(binary)
                visited.add(binary)
            arr[i] = arr[i][:e - 56 * width + 1].rstrip('0') # 확인한 코드는 제거 후 배열에서 오른쪽 0을 다 지운다.
    return total


def code_status(i):     # 너비와 끝점 찾는 함수
    cnt, e = 0, 0       # 암호의 길이와 끝점
    current = '0'       # 암호를 확인하고 값을 저장
    change = 0          # 네번 바뀌는지 파악하기 위한 변수
    for j in range(len(arr[i]))[::-1]:
        if current != arr[i][j]:
            if change == 4:  # 4번 바뀌면 종료
                break
            change += 1
            current = arr[i][j]
        if arr[i][j] == '1':
            if cnt == 0:
                e = j  # 끝 점 기억
            cnt += 1  # 1 개수 세기
        if cnt and arr[i][j] == '0':
            cnt += 1  # 0 개수 세기
    width = cnt // 7    # 7의 몇 배수인지 파악
    return e, width  # 끝점과 너비


def solve_code(code):  # 암호 시작점을 받아 해독한다.
    result = [0]  # 시작부분에 padding을 넣어준다.
    for i in range(8):  # 딕셔너리에 적은 코드와 같으면 그 값인 숫자로 넣어준다.
        result.append(d[code[0 + i * 7:(i + 1) * 7]])
    odd_sum, even_sum = 0, 0
    for i in range(1, 9):
        if i % 2:  # 홀수일 때와 짝수일 때 각각의 합을 찾는다.
            odd_sum += result[i]
        else:
            even_sum += result[i]

    if (odd_sum * 3 + even_sum) % 10:  # 계산 후 10으로 나누어 떨어지는지 판별
        return 0
    else:
        return sum(result)


d = {'0001101': 0, '0011001': 1, '0010011': 2, '0111101': 3, '0100011': 4, \
     '0110001': 5, '0101111': 6, '0111011': 7, '0110111': 8, '0001011': 9}
hex_c = {'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15}
for tc in range(1, 1 + int(input())):
    n, m = map(int, input().split())
    arr = list(set([input().strip().rstrip('0') for _ in range(n)]))    # 오른쪽에 0 제거, set로 중복제거한 후 다시 리스트에 담는다.
    visited = set()     # 중복된 코드가 있는지 확인
    print(f'#{tc} {search_code()}')

🔍 結果