[프로그래머스][LV.2] 모음사전 | python3

2025. 3. 15. 13:55프로그래머스/LV.2

문제링크:  모음사전


문제설명

사전에 알파벳 모음 'A', 'E', 'I', 'O', 'U'만을 사용하여 만들 수 있는, 길이 5 이하의 모든 단어가 수록되어 있습니다. 사전에서 첫 번째 단어는 "A"이고, 그다음은 "AA"이며, 마지막 단어는 "UUUUU"입니다.

단어 하나 word가 매개변수로 주어질 때, 이 단어가 사전에서 몇 번째 단어인지 return 하도록 solution 함수를 완성해주세요.

 

제한조건

- word의 길이는 1 이상 5 이하입니다.
- word는 알파벳 대문자 'A', 'E', 'I', 'O', 'U'로만 이루어져 있습니다.


 

문제풀이

permutation은 중복을 허용하지 않기 때문에 리스트에 각 문자를 5개씩 넣어줬다.

 

조합을 구해서 리스트에 추가하는 부분에서 append를 써서

TypeError: sequence item 0: expected str instance, tuple found

오류가 났었다.

 

 

더보기

♣ append()와 extend()의 차이점

🔹 append(): 리스트에 그 자체로 추가

  • 리스트 안에 리스트가 들어감
  • append()는 하나의 객체를 통째로 추가함.

🔹 extend(): 리스트를 개별 요소로 풀어서 추가

  • 리스트 안에 리스트가 아니라, 개별 원소가 추가됨
  • extend()는 반복 가능한(iterable) 객체를 풀어서 추가함.

🔹 append() vs extend() 차이점 요약

메서드                   동작 방식                                                                    예제                                     결과

append(x) 리스트에 그 자체로 추가 lst.append([4, 5]) [1, 2, 3, [4, 5]]
extend(x) 리스트를 개별 요소로 풀어서 추가 lst.extend([4, 5]) [1, 2, 3, 4, 5]

🔥 문제에서 append()를 사용하면 안 되는 이유

per = []
for i in range(1, 6):
    per.append(product(alpha, repeat=i))  # ❌ 잘못된 코드

🚨 이렇게 하면 per에 product()의 객체가 리스트로 들어감.
즉, per 안에는 [<itertools.product object at 0x...>] 같은 값이 들어가게 됨.

 올바른 코드 (extend() 사용)


🎯 결론

  • append() → 리스트 자체를 요소로 추가
  • extend() → 리스트를 개별 요소로 풀어서 추가
  • 순열이나 조합을 리스트에 추가할 때는 extend()를 써야 한다! 

그리고 alpha=['A','E','I','O','U']*5 이렇게 리스트로 말고

alpha='AEIOU' * 5 문자열로 줘도 됨. => 반복 가능한 객체라

 

나의코드

from itertools import permutations
def solution(word):
    answer = 0
    alpha=['A','E','I','O','U']*5 # 중복 허용 조합을 만들기 위해
    per=[] # 조합
    # result=[] # 문자열
    for i in range(1,6):
        per.extend(permutations(alpha,i))
        
    result=list(set(''.join(p) for p in per))
    result.sort()
    answer=result.index(word)
            
    return answer+1 # 몇번째이기 때문에 인덱스 +1

 


 

더보기

참고하기

 

from itertools import product

def solution(word):
    vowels = "AEIOU"
    
    # 길이 1~5까지 가능한 모든 단어 생성
    dictionary = []
    for i in range(5):
        for comb in product(vowels, repeat=i+1): # 길이가 i+1인 모든 조합 생성
            dictionary.append("".join(comb))
    
    # 사전순 정렬
    dictionary.sort()
    
    # 입력된 단어의 위치 반환 (0부터 시작하므로 +1)
    return dictionary.index(word) + 1

product를 이용하여 푼 풀이

📌 itertools.product() 정리

🔹 역할:

  • 주어진 문자열에서 **중복을 허용한 모든 순열(중복 순열, 데카르트 곱)**을 생성

🔹 사용법:

from itertools import product

vowels = "AEIOU"
list(product(vowels, repeat=2))  

✅ 결과:

[('A', 'A'), ('A', 'E'), ('A', 'I'), ..., ('U', 'U')]

➡ "AA", "AE", "AI", ..., "UU" 형태로 변환 가능

🔹 코드에서의 역할:

for i in range(5):
    for comb in product(vowels, repeat=i+1):
        dictionary.append("".join(comb))

길이가 1~5인 모든 단어를 생성하여 리스트에 추가
사전순 정렬 후 인덱스로 단어 순서 찾기

 

🔹 비교:

함수                          중복 허용         순서 고려         예제(AB, repeat=2)                          결과
product() product("AB", repeat=2) AA, AB, BA, BB
permutations() permutations("AB", 2) AB, BA
combinations() combinations("AB", 2) AB

👉 product()는 중복 허용 & 순서 고려하는 "중복 순열" 생성 함수! 


def solution(word):
    answer = 0
    for i, n in enumerate(word):
        answer += (5 ** (5 - i) - 1) / (5 - 1) * "AEIOU".index(n) + 1
    return answer

 

🛠 핵심 아이디어

  • 각 자리에서 알파벳(A, E, I, O, U)이 가질 수 있는 조합 개수를 이용해 위치를 계산
  • A, E, I, O, U는 각각 0, 1, 2, 3, 4의 인덱스를 가짐
  • 이를 기반으로 자리값을 반영해 가중치를 계산

🔎 코드 분석

def solution(word):
    answer = 0
    for i, n in enumerate(word):  # word의 각 문자에 대해 반복
        answer += (5 ** (5 - i) - 1) / (5 - 1) * "AEIOU".index(n) + 1
    return answer

📌 변수 정리

변수                                                설명
word 주어진 단어
i 현재 문자(알파벳)의 위치 (0부터 시작)
n 현재 문자 (A, E, I, O, U 중 하나)
"AEIOU".index(n) 현재 문자가 A, E, I, O, U 중 몇 번째인지 (0~4)

💡 숫자 계산 방식

주어진 단어가 몇 번째인지 구하는 방식은 자리값에 따른 가중치를 더하는 방식입니다.

1️⃣ (5⁵ - 1) / (5 - 1)

  • 자리값에 따라 앞에 얼마나 많은 단어가 있는지 결정하는 등비수열 합 공식
  • 5⁵ - 1 / 5 - 1 = 781
    → 예를 들어, 첫 번째 문자가 바뀔 때마다 781개씩 이동

2️⃣ 자리별 계산

  • "AEIOU".index(n) : 현재 문자의 인덱스를 가져옴 (A = 0, E = 1, ...)
  • 위치별 가중치 계산
    • 첫 번째 자리 → 781 * 인덱스
    • 두 번째 자리 → 156 * 인덱스
    • 세 번째 자리 → 31 * 인덱스
    • 네 번째 자리 → 6 * 인덱스
    • 다섯 번째 자리 → 1 * 인덱스

3️⃣ +1 보정

  • 모든 단어의 위치는 1부터 시작하므로, 각 자리에서 +1을 추가

예제 계산

🔹 word = "EIO"

문자 자리(i) "AEIOU".index(n) 가중치 계산 결과
E 0 1 781 * 1 + 1 782
I 1 2 156 * 2 + 1 314
O 2 3 31 * 3 + 1 94
합계       1190

🔹 따라서 "EIO"는 1190번째 단어임!


🎯 최종 요약

  1. 각 자리(A, E, I, O, U)에 따른 가중치(781, 156, 31, 6, 1)를 곱하여 계산
  2. "AEIOU".index(n)을 사용하여 알파벳의 위치를 찾음
  3. 각 자리의 값을 합산하여 최종 순서(answer)를 구함
  4. 최종 결과를 1부터 시작하는 순번으로 반환

def solution(word):
    preset = dict()
    preset['A'] = [1,1,1,1,1]
    preset['E'] = [782,157,32,7,2]
    preset['I'] = [1563,313,63,13,3]
    preset['O'] = [2344,469,94,19,4]
    preset['U'] = [3125,625,125,25,5]
    ######### 사전이므로 idx4부터 따라올라가면
    ########## preset 산출가능함

    ans=0
    for idx, key in enumerate(word):
        ans+=preset[key][idx]
    return ans