ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준 2922] 즐거운 단어 (Python)
    Algorithm & Problem Solving/브루트포스(Brute Force) 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)

     

    결과

     

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

    댓글

Designed by Tistory.