본문 바로가기

SWEA_알고리즘

[SWEA] 4047. 영준이의 카드 카운팅 - Python

문제

 

최근 영준이는 카드 게임에 꽂혀 있다.
영준이가 하는 카드 게임에는 한 덱의 카드가 필요한데 여기서 얘기하는 “한 덱”이란 스페이드, 다이아몬드, 하트, 클로버 무늬 별로 각각 A, 2~10, J, Q, K의 라벨 즉 4개의 무늬 별로
각각 13장씩 총 52장의 카드가 있는 모음을 의미한다.

편의상 A는 1, J, Q, K는 11, 12, 13으로 하여 1~13의 숫자가 카드에 적혀있다고 하자.
영준이는 몇 장의 카드를 이미 가지고 있는데 게임을 하기 위해서 몇 장의 카드가 더 필요한지 알고 싶어 한다.
그리고 이미 겹치는 카드를 가지고 있다면 오류를 출력하고자 한다.
지금 가지고 있는 카드의 정보가 주어지면 이 작업을 수행하는 프로그램을 작성하라.


[입력]

맨 위 줄에 테스트케이스의 개수가 주어진다.

각 테스트케이스 별로 순서대로 첫 번째 줄에 지금 영준이가 가지고 있는 카드에 대한 정보 S (1 ≤ |S| ≤ 1000)가 주어진다.
S는 각각 3자리로 표현되는 카드들의 정보를 붙여서 만든 하나의 문자열인데 각 카드는 TXY 꼴로 표현되며,

T는 카드의 무늬(S, D, H, C)이며 XY는 카드의 숫자 (01 ~ 13)이다.

[출력]

각 테스트케이스 별로 순서대로 한 줄씩 답을 출력하는데, 문자열 S를 보고 지금 무늬 별로(S, D, H, C 순서로) 몇 장의 카드가 부족한지 출력하여라.

이미 겹치는 카드가 있다면 문자열 “ERROR” (쌍따옴표는 출력하지 않는다)를 출력한다

 

 

★ 시작하기 전에

몇가지 시작하기 전에 정리해야할 것들이 많다. 이문제에는 풀기 전 입력값, 초기 변수에 대한 정리가 필요하다고 생각했다.

1. 우선, 문자열 한 덩어리로 입력값이 정해지며, 그 덩어리 내에 여러 정보가 담겨 있다. (문자열에 대한 분리 필요)

2. 카드의 갯수는 정해져 있다. (불변하다.)

이 중 1번이 까다롭다고 생각했다. 문자와 숫자가 합쳐진 형태의 정보이기 때문에 효율적으로 구분하는게 중요하다.

 

각 카드별 14개의 항목을 지닌 이차 배열 리스트를 만들어서 시작해보았다.

그러면.... 'S', 'D', 'H', 'C'와 이차 배열의 인덱스는 어떻게 연결하지....?

내가 생각한 방법은 모든 경우를... 나누어 주는 방법...ㅠㅠ 이거 말고는 없나....

 

○ 나의 풀이

T =int(input())

for case in range(1,T+1):
    words = input()
    n = len(words)
    # 52개의 카드를 구분하여 나누었고 나오는 갯수만큼 +1 할 예정이다.
    board = [[0 for _ in range(13)] for _ in range(4)]
    # for하고 나와 -1이면 error가 나오게 하려고 변수 지정함.
    ans = 0
    for i in range(0, n, 3):
    	# 4가지 경우에 대해 나누어 생각한 후 복붙.. 했다...; 만약.. 100가지 경우라면..
        # 이게 맞는건가??? 가능한가???? 100번 복사..
        if words[i] == 'S':
        	# 인덱스 접근은 잘했다고 생각한다. 문자열에서 인덱스 접근은 효율적이다... 
            # 다만 슬라이싱을 쓴건... 또 다른 문제... 그냥 words[i+1] + words[i+2]가 나은가?
            num = int(words[i+1:i+3])
            board[0][num-1] += 1
            if board[0][num-1] > 1:
                ans = -1
                break
        elif words[i] == 'D':
            num = int(words[i + 1:i + 3])
            board[1][num - 1] += 1
            if board[1][num-1] > 1:
                ans = -1
                break
        elif words[i] == 'H':
            num = int(words[i + 1:i + 3])
            board[2][num - 1] += 1
            ans += 1
            if board[2][num-1] > 1:
                ans = -1
                break
        else:
            num = int(words[i + 1:i + 3])
            board[3][num - 1] += 1
            ans += 1
            if board[3][num-1] > 1:
                ans = -1
                break
    if ans == -1:
        print('#{} ERROR'.format(case))
    else:
        print('#{} {} {} {} {}'.format(case, 13- sum(board[0]), 13- sum(board[1]), 13- sum(board[2]), 13-sum(board[3])))

 

 

 

뭔가 난잡하다... 난잡해... 정말  깔끔하게 생각이 들지 않아... ㅠㅠ 빠르게 다른 사람들의 코드를 스캔했다...

그 중 대단하다고.. 깔끔하고 이렇게 되고 싶은 코드를 외우고 익히자.

★☆ 빛.. 풀이...

# 이거 깔끔하다.. 진짜 깔끔하게 푸는 방법이다. 본받고 싶다.. ㅠㅠ

T = int(input())

for case in range(1,T+1):
    words = input()
    n = len(words)
    # dict을 이용하여 정리하였다.
    # 하지만 단순히 dict이 아니라... 각 인덱스 0에 카운팅 총합을 넣어놨다... 22열 확인!!
    card = {
        'S' : [0] * 14,
        'D' : [0] * 14,
        'H' : [0] * 14,
        'C' : [0] * 14
    }
    # 마지막 정리를 위해 count 초기화
    count = [0] *4
    
    result = 0
    for i in range(0, n, 3):
        T, num = words[i], int(words[i+1] + words[i+2])
        if card[T][num] == 0:
            card[T][num] += 1
            card[T][0] +=1    # 이런 식으로 결과를 낼 때 사용할 수 있도록 활용한다!!
        else:
            result = 'ERROR'
            break
    else:
    	# 이런 방식도 알아두자
        text = 'SDHC'
        for idx, val in enumerate(text):
            count[idx] = 13 - card[val][0]
        result = ' '.join(map(str, count))

    print('#{} {}'.format(case, result))

 

이번 문제를 통해 익혀둘 것은 문제에 들어가기 전 변수 정의, 입력값 정리 를 하는 방법이라고 생각한다. 무식하게 도전하면 되기야 된다. 하지만 수정하기 어렵다.

문자와 숫자로된 문자열은 dict을 활용할 수 있으며, index로 탐색할 수 있다.

마지막으로 무엇보다 항상 idx 편하게 하기 위해 활용 안한 0 인덱스를 활용하는 방법도 알 수 있었다!

'SWEA_알고리즘' 카테고리의 다른 글

[SWEA] 11611. 배열 최소 합 - Python  (0) 2021.03.02
[SWEA] 1224. 계산기3 - Python  (0) 2021.03.02
[SWEA] 4837. 부분집합의합 - Python  (0) 2021.02.16