본문 바로가기
Dev/Algorithm

[프로그래머스] 숫자야구 문제 (Level 2) Python 풀이

by 아임웬디 2020. 2. 21.

문제 설명

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

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

* 숫자는 맞지만, 위치가 틀렸을 때는 볼
* 숫자와 위치가 모두 맞을 때는 스트라이크
* 숫자와 위치가 모두 틀렸을 때는 아웃

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

A : 123
B : 1스트라이크 1볼.
A : 356
B : 1스트라이크 0볼.
A : 327
B : 2스트라이크 0볼.
A : 489
B : 0스트라이크

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

 

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

 

제한사항

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

입출력 예

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

https://programmers.co.kr/learn/courses/30/lessons/42841

 

코딩테스트 연습 - 숫자 야구 | 프로그래머스

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

programmers.co.kr


완전탐색?

 

'무식해 보여도 사실은 최고의 방법일 때가 있지요. 가능한 모든 상황을 조사해 문제를 풀어보세요.'라고 프로그래머스에 간단하게 명시되어있다. 비슷한 맥락으로, Brute-force Search, 전체 탐색이라고도 불리며 말그대로 모든 경우의 수를 모두 탐색하며 문제를 해결하는 방법을 뜻한다.

 


작성 코드

https://github.com/Sunkyoung/AlgoGo/blob/master/Programmers/number_baseball_game.py

 

코드로 구현해내는 데에 어려움을 느껴서 완전 탐색을 개념을 이해하기 위해, 고득점 kit에 있는 완전 탐색 다른 문제들을 먼저 쉬운 것부터 풀었는데 그건 한번에 슈루룩 풀었는데 숫자야구를 완벽히 이해하고 구현하는데에는 꽤 오랜 시간이 걸렸다. 다음에 이런 문제 풀면 슈루룩 풀 수 있기를 ㅠㅠ

그리고 다른 많은 코드들을 참고하면서 풀었다. (역시 숫자야구는 사람끼리 하는 걸로) 그 중 거의 비슷하게 많이 참고했던 코드이다. 감사합니다.. https://ihatecucumber.tistory.com/50

import itertools

def solution(baseball):
    answer = 0
    # 모든 경우의 수, all에 담음
    all = list(itertools.permutations(range(1,10),3)) # 1-9까지의 수 세 개의 수로 구성한 순열
    for a in all:
        flag = False
        for round in baseball:
            num = str(round[0])
            s, b = check(a, num) # 경우의 수와 질문한 숫자 간의 s, b 카운트 비교
            if s != round[1] or b != round[2] :
                flag = False
                break
            flag = True # 카운트가 같다면 flag를 true로 설정
        if flag is True: # input으로 주어진 케이스에 대해 모두 만족한다면 answer + 1
            answer += 1
    return answer

def check(a, num):
    s , b = 0 , 0 
    for i in range(3) :
        # strike가 되는 경우
        if str(a[i]) == num[i] :
            s += 1
            continue # continue 사용안하면 중복 볼 카운트 됨
        # ball이 되는 경우
        if str(a[i]) in num :
            b += 1
    return s, b

+)

해당 코드에서 모든 경우의 수를 만들 때 itertool 라이브러리로 쉽게 순열을 이용하여 만들었다.

순열과 조합을 활용하는 문제에서 더 편하게 문제를 풀 수 있을 것 같다!

 

Combinatoric generators:

Iterator Arguments Results

product()

p, q, … [repeat=1]

cartesian product, equivalent to a nested for-loop

permutations()

p[, r]

r-length tuples, all possible orderings, no repeated elements

combinations()

p, r

r-length tuples, in sorted order, no repeated elements

combinations_with_replacement()

p, r

r-length tuples, in sorted order, with repeated elements

product('ABCD', repeat=2)

 

AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD

permutations('ABCD', 2)

  AB AC AD BA BC BD CA CB CD DA DB DC

combinations('ABCD', 2)

 

AB AC AD BC BD CD

combinations_with_replacement('ABCD', 2)

 

AA AB AC AD BB BC BD CC CD DD

출처 : https://docs.python.org/2/library/itertools.html

댓글