[Programmers] 메뉴 리뉴얼

eunseo kim 👩‍💻·2021년 6월 24일
0

🎯 programmers > 2021 KAKAO BLIND RECRUITMENT > 메뉴 리뉴얼


🤔 나의 풀이

📌 문제

- programmers > 2021 KAKAO BLIND RECRUITMENT > 메뉴 리뉴얼

📌 날짜

2021.06.24

📌 시도 횟수

1 try

💡 나의 Code

from itertools import combinations
from collections import defaultdict


def solution(orders, course):
    order_dict_list = [defaultdict(int) for _ in range(len(course))]

    for order in orders:
        for idx, size in enumerate(course):
            order_combinations = combinations(sorted(order), size)
            for m in order_combinations:
                order_dict_list[idx][m] += 1

    answer = []
    for menu_dict in order_dict_list:
        if menu_dict:
            result = sorted(menu_dict.items(), key=lambda x: x[1], reverse=True)
            most_ordered = result[0][1]
            for other in result:
                if most_ordered > 1 and other[1] == most_ordered:
                    answer.append("".join(other[0]))
                else:
                    break

    return sorted(answer)

💡 문제 해결 방법

💡 새롭게 알게 된 점

❌ 개선할 점 / 오답의 원인

- 비낕 for문이 course를 기준으로 돈다면 2개의 for문을 하나로 만들 수 있을 것 같다.

📌 1차 개선

💡 문제 해결 방법

- 바깥 for문을 courses로 바꿔주었다.
- python의 Counter과 most_common() 함수를 이용했다. 

💡 Code : 방법 1

from itertools import combinations
from collections import Counter


def solution(orders, course):
    result = []

    # 각 course 값에 대해 코스요리 후보 구하기
    for size in course:
        # 크기가 현재 course의 size인 모든 조합 구하기
        order_combinations = []
        for order in orders:
            order_combinations += combinations(sorted(order), size)

        # 해당 course에서 가장 많이 주문된 메뉴 조합을 찾아서 result에 저장
        most_ordered = Counter(order_combinations).most_common()
        for menu, ordered_num in most_ordered:
            if ordered_num > 1 and ordered_num == most_ordered[0][1]:
                result.append("".join(menu))
    return sorted(result)

💡 새롭게 알게 된 점

Counter('hello world').most_common()
>> [('l', 3), ('o', 2), ('h', 1), ('e', 1), (' ', 1), ('w', 1), ('r', 1), ('d', 1)]

Counter('hello world').most_common(1) # 앞에서 1번째만 출력
>> [('l', 3)]

❌오답의 원인 : +=append

  • 위의 코드에서 사실 처음에는 order_combinations += combinations(sorted(order), size) 대신 order_combinations.append(combinations(sorted(order), size))를 사용했다.
  • 즉, += 대신 append를 사용했더니 틀린 결과가 나왔다. 왜 그럴까?

📌+=append

디버깅을 해보니까 다음과 같이 출력됐다.

# 1) append
order_combinations.append(combinations(sorted(order), size))
print(order_combinations)
>> <itertools.combinations object at 0x00000171A8C2A810>

# 2) +=
order_combinations += combinations(sorted(order), size)
print(order_combinations)
>> [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
  • 즉, combinations의 경우, 리턴 값이 다음과 같이 combinations(iterable: Iterable[_T], r: int) -> Iterable[Tuple[_T]]인데,
    append를 하게 되면 Iterable 객체가 저장되기 때문에 <itertools.combinations object at 0x00000171A8C2A810> 이렇게 출력됐던 것이다.
  • 반면, +=를 하게 되면 신기하게 combinations의 리턴 값인 <itertools.combinations object at 0x00000171A8C2A810>를 자동으로 list로 변환해서 저장해주었다. 따라서 이후의 값이 제대로 나올 수 있었던 것이다.

💡 참고 / +=appendextend

# combinations(iterable: Iterable[_T], r: int) -> Iterable[Tuple[_T]]
result = combinations([1, 2, 3, 4, 5], 2)
print(result)
# >> <itertools.combinations object at 0x000001C6369CA8B0>

# 📌list(combinations)
result = list(combinations([1, 2, 3, 4, 5], 2))
print(result)
# [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]

# 📌+= combinations
result = []
result += combinations([1, 2, 3, 4, 5], 2)
print(result)
# [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]

# 📌extend(combinations)
result = []
result.extend(combinations([1, 2, 3, 4, 5], 2))
print(result)
# [(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]

# 📌append(list(combinations)) : 💡[[...]]꼴로 저장되는 것에 유의하자. 이중 list가 된다.💡
result = []
result.append(list(combinations([1, 2, 3, 4, 5], 2)))
print(result)
# [[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]]

profile
열심히💨 (알고리즘 블로그)

0개의 댓글