본문 바로가기

Study/알고리즘

[python] 프로그래머스 - 숫자 야구

문제 설명

숫자 야구 게임이란 2명이 서로가 생각한 숫자를 맞추는 게임입니다.

각자 서로 다른 1~9까지 3자리 임의의 숫자를 정한 뒤 서로에게 3자리의 숫자를 불러서 결과를 확인합니다. 그리고 그 결과를 토대로 상대가 정한 숫자를 예상한 뒤 맞힙니다.

 

* 숫자는 맞지만, 위치가 틀렸을 때는 볼

* 숫자와 위치가 모두 맞을 때는 스트라이크

* 숫자와 위치가 모두 틀렸을 때는 아웃

 

예를 들어, 아래의 경우가 있으면,

A : 123

B : 1 스트라이크 1 볼.

A : 356

B : 1 스트라이크 0 볼.

A : 327

B : 2 스트라이크 0 볼.

A : 489

B : 0 스트라이크 1 볼.

 

이때 가능한 답은 324와 328 두 가지입니다.

질문한 세 자리의 수, 스트라이크의 수, 볼의 수를 담은 2차원 배열 baseball이 매개변수로 주어질 때, 가능한 답의 개수를 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 질문의 수는 1 이상 100 이하의 자연수입니다.
  • baseball의 각 행은 [세 자리의 수, 스트라이크의 수, 볼의 수]를 담고 있습니다.

입출력 예

[[123, 1, 1], [356, 1, 0], [327, 2, 0], [489, 0, 1]] 2

접근법

와!! 완전탐색 너무 어려워!! 처음에 완전 잘못된 방법으로 해결책을 생각하는 바람에 몇 시간을 삽질했는지 모른다.

처음 생각한 방법은 이렇다.

  1. 1 ~ 9까지 모든 조합을 순열로 만들어낸다 => itertools 사용.
  2. 사용자가 입력한 각 숫자를 순회하면서 조건에 맞는 숫자들만 골라낸다.
    • 123에 1 스트라이크인 경우, "1**", "*2*", "**3"인 것들을 골라내고, ball이 1이면 1이나 2나 3이 들어있는 숫자만 남겨놓는 방식.
    • ball이 2면 12, 13, 23을 가진수만 뽑아낸다.
  3. strike가 1이면 strike가 2면.. ball이 1이면......? 로직이 길어지니 꼬여만가고 수많은 if문만 남을 뿐이었다..

혼자만의 힘으로 풀기 위해 노력했으나 포기하고 다른 사람들의 풀이를 참고해봤다. 뒤통수를 맞은 기분이었다.. 각 숫자마다 strike와 ball을 계산해서 일치하는 숫자만 남기면 되는 것이었다.. 해결책을 달리 생각하니 쉽게 코드가 작성됐다!!! 

예를 들면,

  1. 123에 1 스트라이크 0볼일때 모든 수를 순회하면서 1스트라이크 0 볼인 숫자들만 담은 리스트를 저장한다.
  2. 다음 조건으로 넘어가서 위의 로직을 반복한다

모든 수의 조합에서, 조건(strike와 ball)에 맞는 숫자들만 두고 맞지 않는 것들은 걸러내며 최종 숫자만을 남겨놓는 숫자 야구 게임이었다.

내 코드

import itertools

def check_same(check, num):
    strike, ball = (0,0)
    for i in range(3):
        if check[i] == num[i]:
            strike += 1
        if check[i] in num:
            ball += 1
    return (strike, ball-strike) # ball에 strike까지 count되니 그만큼 빼주자.
            
def solution(baseball):
    number = [str(x) for x in range(1,10)]
    allNumber = list(map(''.join, itertools.permutations(number,3)))
    for num, strike, ball in baseball:
        allNumber = [check for check in allNumber if check_same(check, str(num)) == (strike, ball)]
    return len(result)

그래도 이번 문제는 정답에 많이 근접했던 것 같다. 조건에 맞는 숫자를 거르는 부분의 로직만 바꾸니 잘 돌아가더라. 비록 다른 사람들이 어떻게 접근했는지를 보고 해답을 얻었지만, 정답에 가까이 접근했다는 점에 의의를 두려 한다.