알고리즘/백준

[백준] 2503번: 숫자 야구 / Python

히똔 2021. 12. 23. 23:10
728x90
반응형

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

 

2503번: 숫자 야구

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

www.acmicpc.net

문제 접근 방법

1. 스트라이크, 볼 갯수로 경우의 수 나누기

처음에는 스트라이크, 볼 갯수에 따라 경우의 수를 나눠서 구하려고 했다.

if strike == 0 :
elif strike == 1 :
elif strike == 2:
else:

if ball == 0:
...

위와 같이 하려다가 경우의 수가 너무 복잡해져서
짜놓은 코드를 다 지우고 다시 생각해보았다. (그런데 다른 분들 풀이를 보니 이렇게 푸신 분도 딱 한분 봤다.. 존경)

2. 숫자 야구 함수를 만들기

영수가 생각한 정답과 민혁이가 생각한 추측 숫자를 매개변수로 설정하면 스트라이크, 볼의 갯수를 리턴하도록 하는 함수를 짰다.
그리고 그 리턴값이 영수가 대답하는 스트라이크와 볼의 갯수가 일치하는 지 확인하는 문제 풀이 방식이다.

문제풀이

from itertools import permutations

# candidate: 영수가 생각한 숫자, guess: 민혁이가 추측한 숫자
def check(candidate, guess): # strike 와 ball 출력하는 함수
    strike, ball, nothing=0,0,0
    for i in range(3):
        if candidate[i] == guess[i] : strike +=1 # strike 확인 하기
        elif candidate[i] not in guess : nothing+=1# strike ball 도 아닐때
    ball=3-nothing-strike
    return(strike, ball)


numbers=[str(i+1) for i in range(9)] # 1~9
candidate=list(map("".join,permutations(numbers,3))) # 정답 가능성 있는 후보 - str으로 만들기

N=int(input())

for i in range(N):
    int_guess, strike, ball = map(int,input().split())
    guess=str(int_guess)
    new_candidate=[] # 새로운 후보군 선언
    for j in candidate:
        c_strike, c_ball=check(j,guess) # check 함수 사용
        if c_strike==strike and c_ball == ball : #check 함수랑 같으면
            new_candidate.append(j) # 새로운 후보군 리스트에 추가
    candidate=new_candidate

print(len(candidate))

비교 분석

다른 분들의 풀이를 보다보니 대부분 비슷한 방식으로 코드를 짰다.
그런데 두가지 다른 부분이 있었다.

1. ball 갯수 구하는 방법

나는 strike도 ball 도 아닌 nothing 을 구해서 ball = 3-strike-nothing 했다.

strike, ball, nothing=0,0,0
for i in range(3):
    if candidate[i] == guess[i] : strike +=1 # strike 확인 하기
    elif candidate[i] not in guess : nothing+=1 # strike도 ball 도 아닐때
ball = 3-nothing-strike

그런데 ball을 바로 구하신 분들이 많았다. 그 중에서 제일 깔끔한 코드는 다음과 같다

for j in range(3):
    test[j] = int(test[j])
    if test[j] in num[i]: # 추측한 값이 정답 값에 속해있는지 확인하고
        if j == num[i].index(test[j]): # 같은 자리에 있으면 
            strike += 1 # 스트라이크
        else: 
            ball += 1 # 같은 자리에 없으면 볼

2. 초기 후보군 설정방법 (숫자 123 ~ 987 겹치지 않게 설정하는 방법)

1~9 까지 담는 number 리스트를 만든후 permutations를 이용해서 겹치지 않게 만들어줬다.

from itertools import permutations

numbers=[str(i+1) for i in range(9)] # 1~9
candidate=list(map("".join,permutations(numbers,3))) # 정답 가능성 있는 후보 - str으로 만들기

그런데 의외로 permutations 사용 안하시고 더 복잡하게 푸신 분들이 더 많았다.

sets = set()
for val in range(100,1000):
    val = str(val)
    if val.count('0')>0:
        continue
    i,j,k = list(val)
    if len(set(([i,j,k])))==3:
        sets.add(str(val))
728x90
반응형