ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2503. [Python]숫자 야구
    Python_알고리즘/Silver III 2023. 7. 13. 19:15

    1. 문제

     

    https://www.acmicpc.net/problem/2503

     

    2503번: 숫자 야구

    첫째 줄에는 민혁이가 영수에게 몇 번이나 질문을 했는지를 나타내는 1 이상 100 이하의 자연수 N이 주어진다. 이어지는 N개의 줄에는 각 줄마다 민혁이가 질문한 세 자리 수와 영수가 답한 스트

    www.acmicpc.net

     

    2. 접근 방법

     

    • 시간 제한: 1초
    • 메모리 제한: 128MB
    • 구현, 순열, 브루트 포스

     

    3. 파이썬 코드

     

    from itertools import permutations
    
    N = int(input())
    # 들어온 숫자 값들을 저장할 리스트
    num_list = []
    # 숫자값과 스트라이크 볼을 저장할 리스트
    base_list = []
    # 없는 숫자를 체크할 리스트
    no_list = []
    # 1~9의 숫자조합을 만들기 위한 리스트
    check_list = [1,2,3,4,5,6,7,8,9]
    # N의 갯수만큼 반복문 시행
    for _ in range(N):
        # input 으로 외친 숫자, 스트라이크 갯수, 볼의 갯수
        baseball = list(map(int,input().split()))
        # input 으로 들어온 숫자를 문자열로 치환
        baseball[0] = str(baseball[0])
        # 볼과 스트라이크가 둘다 0이 아닌 경우 인풋 형태 그대로 리스트한개에 저장
        # 숫자만 따로 별도의 리스트에 저장
        if baseball[1] != 0 or baseball[2] != 0:
            num_list.append(baseball[0])
            base_list.append(baseball)
        # 만약 스트라이크 갯수가 0 이고 볼의 갯수가 0 인 경우 no_list에 없는 값들 추가
        elif baseball[1] == 0 and baseball[2] == 0:
            for l in baseball[0]:
                if l not in no_list:
                    # 정수형으로 다시 변환
                    no_list.append(int(l))
    # 만약 num_list 에 값이 존재할 경우
    if num_list:
        # check_list에 존재하는 값들로 가능한 모든 경우의 수를 생성
        perm_list = list(permutations(check_list,3))
        # 변환한 값들을 세 자리 수로 바꿔서 담을 리스트 생성
        answer = []
        # perm_list의 값들에 대해서
        for i in perm_list:
            # check 라는 문자열 변수를 생성하여 리스트에 값을 추가해줄 예정
            check = ""
            # i 값 한개씩 문자열로 변환하여 check 라는 변수에 더해줌
            for j in i:
                check += str(j)
            # 합쳐진 문자열을 answer 리스트에 추가
            answer.append(check)
        # 정답을 출력할 리스트생성
        answer_list = []
        # num_list 의 갯수가 실제 N으로 들어온 것보다 적을 수 있기 때문에 길이 측정
        num_length = len(num_list)
        # 모든 가능한 경우의 수를 만들어 둔 리스트를 순회함
        for i in answer:
            # 실제 배열의 길이만큼 반복문 시행
            for j in range(num_length):
                # 값들의 스트라이크 갯수와 볼 갯수를 체크하는 변수
                check_s = 0
                check_b = 0
                # 첫째자리 ~ 셋째자리 까지 반복문 시행
                for k in range(3):
                    # 만약 i의 자리가 num_list(실제로 물어본 값)의 자리와 같은 경우 check_s 스트라이크 갯수 증가
                    if i[k] == num_list[j][k]:
                        check_s += 1
                    # 만약 자리의 값이 다를 경우
                    elif i[k] != num_list[j][k]:
                        # 볼인지 확인하기 위해 리스트에 존재하는지 체크하고 있을 경우 볼의 갯수 증가
                        if i[k] in num_list[j]:
                            check_b +=1
                # 이렇게 반복문이 끝난 후 체크 된 스트라이크 갯수와 실제 입력으로 들어온 스트라이크 갯수 비교
                # 체크 된 볼의 갯수와 실제 볼의 갯수 비교
                # 둘다 같은 경우 넘어가고 아닌 경우 break를 통해서 쓸데없는 반복문을 안돌게함.
                if check_s == base_list[j][1] and check_b == base_list[j][2]:
                   pass
                else:
                    break
            # 반복문이 break로 끝나지 않았을 경우 (모두 탐색을 하고 조건에 부합할 경우)
            else:
                # 정답 리스트에 값을 추가
                answer_list.append(i)
        # 이렇게 추가된 값들의 갯수를 출력
        print(len(answer_list))
    # num_list 에 값이 저장되지 않았을 경우
    else:
        # no_list 에 값들을 순회하며 check_list 에 저장된 값을 지워나감
        for i in no_list:
            check_list.remove(i)
        # 지워진 값들을 가지고 가능한 모든 경우의 수를 생성
        perm_list = list(permutations(check_list,3))
        # perm_list의 길이를 출력
        print(len(perm_list))

     

    4. 문제를 풀고난 후 생각

     

    • 쌩 구현 문제는 언제나 풀어도 항상 어렵게 풀린다. 이 문제도 몇일을 고민하다 인터넷 검색을 통해서 약간의 힌트를 얻어서 해결했다.
    • 들어온 값들과 어떻게 값들을 비교할지가 막막하여 고민을 하다가 1~9 중 3개의 숫자를 사용한 순열을 만들어 브루트 포스를 적용시켜라 라는 글을 발견하고 해결을 하였다.
    • 항상 구현문제를 풀때는 고민되는 것이 어떻게 접근하는지가 막막한 문제였다. 아직 경험이 부족하여 여러 방면으로 생각이 떠오르지는 않는다.
    • 1~9중 3개의 숫자를 뽑은 순열에서 각 모든 값을 input 으로 주어진 숫자들과 비교하여 자리가 같은 경우 check_s 라는 임시 변수에 스트라이크 갯수를 증가, 숫자의 위치가 다른 곳에 있을 경우 check_b 이라는 볼의 갯수를 증가시켜 실제로 들어온 input 값에서 S, B 의 갯수와 같은 경우 다음 수로 넘어가고 같지 않을 경우 break를 사용하여 필요없는 반복문을 생략시켰다.
    • 이렇게 반복문을 진행하다 막상 input 값으로 "123 0 0" 등과 같은 인풋값이 한개만 들어올 경우 문제가 생기게 되기 때문에 no_list 에 input 으로 들어온 S와 B의 값이 둘다 0 인경우 그 숫자들을 추가해줬다.
    • 이렇게 추가해준 숫자들을 제외한 숫자들에서 만들 수 있는 순열조합의 갯수를 출력해주는 방식도 추가해 주어서 예외가 발생하지 않도록 막아줬다.

     

    5. 문제를 푸는데 도움이 되는 지식

     

    • 브루트 포스
    • 순열

    'Python_알고리즘 > Silver III' 카테고리의 다른 글

    3273. [Python]두 수의 합  (0) 2023.07.25
    2512. [Python]예산  (0) 2023.07.18
    2597. [Python]줄자접기  (0) 2023.06.17
    1449. [Python]수리공 항승  (0) 2023.06.14
    2346. [Python]풍선 터뜨리기  (2) 2023.06.13

    댓글

Designed by Tistory.