[백준] 4659번 - 비밀번호 발음하기

ungnam·2025년 3월 20일

문제 설명

좋은 패스워드를 만드는 것은 어려운 일이다. 대부분의 사용자들은 buddy처럼 발음하기 좋고 기억하기 쉬운 패스워드를 원하지만, 이런 패스워드들은 보안 문제가 발생한다. 어떤 사이트들은 xvtpzyo 같은 비밀번호를 무작위로 부여해 주기도 하지만, 사용자들은 이를 외우는 데 어려움을 느끼고 심지어는 포스트잇에 적어 컴퓨터에 붙여놓기도 한다. 가장 이상적인 해결법은 "발음이 가능한" 패스워드를 만드는 것으로, 적당히 외우기 쉬우면서도 안전하게 계정을 지킬 수 있어야 한다.

회사 FnordCom은 그런 패스워드 생성기를 만들려고 계획 중이다. 당신은 그 회사 품질 관리 부서의 직원으로 생성기를 테스트해 보고 생성되는 패스워드의 품질을 평가해야 한다. 높은 품질을 가진 비밀번호의 조건은 다음과 같다.

  1. 모음(a, e, i, o, u) 하나를 반드시 포함해야 한다.
  2. 모음이 3개 혹은 자음이 3개 연속으로 오면 안 된다.
  3. 같은 글자가 연속적으로 두 번 오면 안 되지만, eeoo는 허용한다.

이 규칙은 완벽하지 않다. 우리에게 친숙하거나 발음이 쉬운 단어 중에서도 품질이 낮게 평가되는 경우가 많다.


입력

입력은 여러 개의 테스트 케이스로 이루어져 있다.
각 테스트 케이스는 한 줄로 이루어져 있으며, 각 줄에 테스트할 패스워드가 주어진다.
마지막 테스트 케이스는 "end"이며, 패스워드는 한 글자 이상 20글자 이하의 문자열이다.
또한 패스워드는 대문자를 포함하지 않는다.


출력

각 테스트 케이스를 <password> is acceptable. 또는 <password> is not acceptable. 형식으로 출력해야 한다.


접근 방법

1. 기존에 작성한 코드

vowels = 'aeiou'

while True:
    s = input()
    if s == 'end':
        break

    flag = False
    vowel_count = 0
    consonant_count = 0
    prev = ''

    for c in s:
        # 같은 글자가 연속적으로 두 번 오는 경우 (단, ee와 oo는 허용)
        if prev == c and c not in ('e', 'o'):
            flag = False
            break
        else:
            prev = c

        # 모음과 자음 개수 체크
        if c in vowels:
            flag = True
            vowel_count += 1
            consonant_count = 0
        else:
            vowel_count = 0
            consonant_count += 1

        # 모음이 3개 또는 자음이 3개 연속으로 오면 안 됨
        if vowel_count == 3 or consonant_count == 3:
            flag = False
            break

    # 모음이 하나라도 포함되어 있어야 함
    if flag == False:
        print(f'<{s}> is not acceptable.')
    else:
        print(f'<{s}> is acceptable.')

🔹 문제점

  • 모음 포함 여부를 flag로 관리하는데, 다른 조건에서 flag = False가 될 수도 있어 최종적으로 모음이 포함되었는지 판단하기 어려움.
  • 각 조건을 개별적으로 확인하는 대신, return을 활용하면 실패 조건을 빠르게 판단할 수 있음.
  • 불필요한 변수를 줄이고, 조건문을 단순화하면 코드의 가독성이 향상될 수 있음.

2. 개선된 코드

def is_acceptable(s):
    vowels = 'aeiou'
    
    has_vowel = False  # 모음 포함 여부
    vowel_count = 0  # 연속된 모음 개수
    consonant_count = 0  # 연속된 자음 개수
    prev = ''  # 이전 문자 저장

    for c in s:
        if c in vowels:
            has_vowel = True
            vowel_count += 1
            consonant_count = 0
        else:
            vowel_count = 0
            consonant_count += 1
        
        # 모음이 3개 또는 자음이 3개 연속으로 오면 안 됨
        if vowel_count == 3 or consonant_count == 3:
            return False

        # 같은 글자가 연속적으로 두 번 오면 안 됨 (단, 'ee', 'oo'는 허용)
        if prev == c and c not in "eo":
            return False
        
        prev = c

    # 1. 모음이 하나라도 있어야 함
    return has_vowel


while True:
    s = input()
    if s == 'end':
        break

    if is_acceptable(s):
        print(f'<{s}> is acceptable.')
    else:
        print(f'<{s}> is not acceptable.')

🔹 개선된 점

  • is_acceptable(s) 함수를 만들어 가독성을 높였다.
  • has_vowel 변수를 사용하여 모음이 하나라도 포함되어 있는지 명확히 체크했다.
  • return False를 바로 호출하여 불필요한 flag 초기화 문제를 방지했다.
  • 코드가 간결하고 논리적으로 명확해졌다.

3. 정규표현식을 활용한 코드

import re

def is_acceptable(s):
    # 1. 모음을 하나 이상 포함해야 함
    if not re.search(r"[aeiou]", s):
        return False

    # 2. 모음 3개 또는 자음 3개가 연속으로 나오면 안 됨
    if re.search(r"[aeiou]{3}|[^aeiou]{3}", s):
        return False

    # 3. 같은 글자가 연속적으로 두 번 오면 안 되지만, ee와 oo는 허용
    if re.search(r"(.)\1", s) and not re.search(r"(ee|oo)", s):
        return False

    return True


while True:
    s = input()
    if s == "end":
        break

    if is_acceptable(s):
        print(f"<{s}> is acceptable.")
    else:
        print(f"<{s}> is not acceptable.")

🔹 장점

  • re.search()를 활용하여 3개의 조건을 한 줄로 검사할 수 있다.
  • 코드가 매우 짧고 간결해졌다.
  • 정규표현식은 내부적으로 최적화되어 있어 속도가 빠르다.

✨ 핵심 정리

  • 처음에는 flag를 사용했지만, 명확한 변수(has_vowel)를 추가하여 논리를 개선했다.
  • 불필요한 반복문 제거 및 가독성을 높이는 코드 구조 개선이 중요하다.
  • 정규표현식을 활용하면 더 간결하고 빠르게 해결 가능하다.
  • 조건을 최대한 효율적으로 검사하는 것이 포인트! 🚀

profile
꾸준함을 잃지 말자.

0개의 댓글