Algorithm & Problem Solving/브루트포스(Brute Force)

[백준 2922] 즐거운 단어 (Python)

baby_ohgu 2020. 12. 15. 13:53

 

www.acmicpc.net/problem/2922

 

2922번: 즐거운 단어

상근이는 자신이 다니는 학교에서 영어단어를 가장 많이 외우고 있다. 그 비법은 바로 조기교육이었다. 상근이는 젖병을 물기도 전에 영어 단어를 외웠다. 따라서, 지금은 자리에 앉으면 사전을

www.acmicpc.net

 

문제풀이

mo : 모음

ja : 자음

S : 입력값

 

go(s, idx, ch) : 재귀적으로 _에 문자를 놓는 함수, s : 문자열, idx : 인덱스, ch : _에 지금까지 사용한 단어

verify(s) : s가 문제의 조건(자음, 모음 연속 3개인지 아닌지, s에 L이 포함되어 있는지)에 위배하지 않는지 확인

 

_ 에 들어올 수 있는 글자는 모음, L이 아닌 자음, L 3가지 가능 => 3^10 이므로 브루트포스로 해결 가능하다
모음을 사용한 경우에는 A를 사용하여 총 모음의 개수(5개)만큼 곱해준다.
L이 아닌 자음을 사용한 경우는 B를 사용하여 총 자음의 개수(L 제외 20개)만큼 곱해준다.
L을 사용한 경우는 L을 사용하여 1 만큼 곱해준다.

 

1. 문자열 S의 가장 첫 인덱스로부터 처음 만나는 _ 에서 재귀를 시작한다.

 

2. go 함수의 문자열 s에서 _가 없는지 확인한다. => _가 없으면 _를 특정 문자로 전부 채운 경우이다.

- 문자열 s가 문제의 조건에 위배되지 않는지 검증한다.

- 지금까지 _에서 사용한 문자(모음 : A 사용, L 제외 자음:  B사용, L : L사용)에 따라 tmp에 값을 곱해준다. (L 제외 자음 : 20 모음 : 5 L: 1)

- ans와 tmp를 더해준다.

 

3. 문자열에서 재귀를 이용해 _ 만큼 문자를 사용한다.

- 모음의 경우 'A' 사용

- L이 아닌 자음의 경우 'B'사용

- L의 경우 'L' 사용

 

4. 결과(ans)를 출력한다.

 

 

코드

# _ 에 들어올 수 있는 글자는 모음, L이 아닌 자음, L 총 3가지 가능 => 3^10 이므로 브루트포스로 해결 가능
# 모음을 사용한 경우는 A 사용
# 자음을 사용한 경우는 B 사용
# L을 사용한 경우는 L 사용

def verify(s):
    mo = ['A', 'E', 'I', 'O', 'U'] # 모음
    ja = ['B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'] # 자음
    if 'L' not in s: return False # L이 없으면 false
    for i in range(len(s) - 2):
        if s[i] in mo and s[i + 1] in mo and s[i + 2] in mo: return False # 모음 3개 연속인 경우 false
        if s[i] in ja and s[i + 1] in ja and s[i + 2] in ja: return False # 자음 3개 연속인 경우 false
    return True

def go(s, idx, ch): # 문자열 s, 인덱스 idx, 사용한 단어 ch
    global ans
    if '_' not in s: # S에 _가 없는 경우
        if verify(s): # 문자열 s 검증
            tmp = 1
            for y in ch: # 사용한 단어 확인
                if y == 'A': tmp *= 5 # 모음을 사용한 경우 5가지
                elif y == 'B': tmp *= 20 # L이 아닌 자음을 사용한 경우 20가지
                else: tmp *= 1 # L을 사용한 경우 1가지
            ans += tmp
        return
    for i in range(idx, len(s)):
        if s[i] == '_':
            s = s[:i] + 'A' + s[i + 1:] # 모음 사용
            go(s, idx + 1, ch + 'A')
            s = s[:i] + 'B' + s[i + 1:] # L이 아닌 자음 사용
            go(s, idx + 1, ch + 'B')
            s = s[:i] + 'L' + s[i + 1:] # L 사용
            go(s, idx + 1, ch + 'L')
            return

if __name__ == '__main__':
    S = input()
    flag = False
    ans = 0
    for i in range(len(S)):
        if S[i] == '_': # S에서 처음으로 _ 발견하면 그때부터 재귀 시작
            flag = True
            go(S, i, '')
            break
    if not flag: ans = 1 # S에서 _가 한개도 없는 경우
    print(ans)

 

결과

 

문제풀이나 코드에서 이상한 부분 지적은 언제나 환영합니다!