몸과 마음이 건전한 SW 개발자

프로그래머스 [Lv. 2] 메뉴 리뉴얼 {언어 : Python} [코드 리펙토링] 본문

알고리즘

프로그래머스 [Lv. 2] 메뉴 리뉴얼 {언어 : Python} [코드 리펙토링]

스위태니 2024. 5. 3. 15:25

문제 링크

https://school.programmers.co.kr/learn/courses/30/lessons/72411?language=python3

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

정답 코드

from collections import defaultdict

def solution(orders, course):
    answer = []
    orderDict = defaultdict(int)
    lenC = len(course)
    
    def addDict(arr):
        stack = []
        for i in range(26):
            if arr[i]:
                stack.append(chr(i+65))
        tmp = "".join(stack)
        orderDict[tmp] += 1
        return
    
    def dfs(order, lastIdx, idx, arr, wantLen, currentLen):
        if idx >= lastIdx:
            if wantLen == currentLen:
                addDict(arr)
            return
        
        nextArr = arr[:]
        nextArr[ord(order[idx])-65] = 1
        dfs(order, lastIdx, idx+1, nextArr, wantLen, currentLen+1)
        dfs(order, lastIdx, idx+1, arr, wantLen, currentLen)
    
    for order in orders:
        lenO = len(order)
        for c in course:
            dfs(order, lenO, 0, [0 for _ in range(26)], c, 0)
            
    maxCntOrder = [1 for _ in range(11)]
    
    slod = sorted(list(orderDict.items()), key=lambda x: x[1], reverse=True)
    for item in slod:
        for c in course:
            if len(item[0]) == c and item[1] > maxCntOrder[c]:
                maxCntOrder[c] = item[1]
    
    for k in range(11):
        if maxCntOrder[k] > 1:
            for item in slod:
                if len(item[0]) == k and item[1] == maxCntOrder[k]:
                    answer.append(item[0])
                    
    answer.sort()
    return answer

코드 리펙토링

from collections import defaultdict, Counter
from itertools import combinations

def solution(orders, course):
    answer = []
    course_dict = defaultdict(list)

    # Create combinations and count them
    for order in orders:
        order = ''.join(sorted(order))  # Sort to ensure combinations are consistent
        for num in course:
            comb_count = Counter(combinations(order, num))
            for comb, count in comb_count.items():
                course_dict[num].append(''.join(comb))

    # Determine the most frequent combinations for each course size
    for num in course:
        if course_dict[num]:
            counter = Counter(course_dict[num])
            max_count = max(counter.values())
            most_frequent = [comb for comb, count in counter.items() if count == max_count and count > 1]
            answer.extend(most_frequent)

    return sorted(answer)

풀이 방법

  1. orders의 order를 조합한다.
  2. order와 코스의 종류에 따라 key를 조합한다.
    1. 예를 들어 order가 ABCD이고 course : [2, 3, 4] 에서 2인 경우
      1. AB, AC, AD, BC, BD, CD 를 만들 수 있다.
      2. 리스트로 만든 이유는
        1. DCBA로 조합을 만들면 DC, DB, DA, CB, CA, BA를 만들 수 있지만 순서가 달라 다르다고 판단할 수 있다.
        2. 따라서 리스트의 번호로 확인해줬다.
  3. 조합한 키를 바탕으로 해당 코스후보가 몇 번 주문되었는지 확인한다.
  4. 그 중 최대로 조합된 코스후보를 answer에 넣고 정렬한 뒤 반환한다. 

느낀점

  • 꽤 오래 걸리고 코드 가독성도 떨어져서 gpt선생님의 도움을 받아 코드를 리펙토링 했다.
  • 코드 줄 수가 2배로 줄었으며 속도 또한 빠르다.