-
2503. [Python]숫자 야구Python_알고리즘/Silver III 2023. 7. 13. 19:15
1. 문제
https://www.acmicpc.net/problem/2503
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