[programmers/CodingTest/Python]メニューの更新


問題の説明


レストランを経営するスカフィーは、コロナ19による不況を克服するため、メニューの再設計を検討している.
以前は単品しか提供していなかったメニューを組み合わせて、セットで再組み合わせして、新しいメニューを提供することにしました.どの単品メニューを組み合わせてセットメニューを構成するかを考えた「scapi」は、以前のお客様一人一人が注文したときに一番多かった単品メニューをセットメニューにすることにしました.
しかし、少なくとも2つの単品メニューが選択できることを望んでいます.また、少なくとも2名以上のお客様からご注文いただいた単品メニューの組み合わせについては、コースメニューの候補リストにのみ入れることにしました.
例えば、6名様からご注文いただいた単品メニューの組み合わせは以下の通りです.
(お客様1人につき2つ以上の単品メニューを注文しなければなりません.各単品メニューはアルファベットA~Zで表示されます)
손님 번호	주문한 단품메뉴 조합
1번 손님	A, B, C, F, G
2번 손님	A, C
3번 손님	C, D, E
4번 손님	A, C, D, E
5번 손님	B, C, F, G
6번 손님	A, C, D, E, H
最も頻繁に注文される単品メニューの組み合わせに基づいて、skapiは次のコースメニュー構成候補オプションを作成します.
코스 종류		메뉴 구성		설명
요리 2개 코스	A, C		1번, 2번, 4번, 6번 손님으로부터 총 4번 주문됐습니다.
요리 3개 코스	C, D, E		3번, 4번, 6번 손님으로부터 총 3번 주문됐습니다.
요리 4개 코스	B, C, F, G	1번, 5번 손님으로부터 총 2번 주문됐습니다.
요리 4개 코스	A, C, D, E	4번, 6번 손님으로부터 총 2번 주문됐습니다.

[質問]


各顧客が注文した単品メニューが文字列形式でリストされた並べ替え注文と、「Scapi」が追加したいセットを構成する単品メニューの数の並べ替えcourseをパラメータとする場合.ソリューション関数を完了し、「scapi」を新しく追加したコースのメニュー構成を文字列で並べて返してください.

[制限]

  • Ordersアレイのサイズは2つの20を超えない.
  • Orders配列の各要素は、2または10より大きい文字列です.
    -各文字列は大文字のみで構成されます.
    -各文字列に同じ文字が重複していません.
  • course配列のサイズは10を超えない.
    -course配列の各要素の自然数は、2以下の昇順に並べられます.
    -course配列に重複する値はありません.
  • 正解各メニューの構成を文字列で並べ、辞書順に昇順に並べて返してください.
    -配列内の各要素に格納されている文字列も、アルファベット順に昇順に並べられている必要があります.
    -一緒に注文したメニュー構成が複数の場合は、すべて梱包して返します.
    -ordersパラメータとcourseパラメータは、返される配列の長さが少なくとも1であることを指定します.
  • [I/O例]

    orders												course	result
    ["ABCFG", "AC", "CDE", "ACDE", "BCFG", "ACDEH"]		[2,3,4]	["AC", "ACDE", "BCFG", "CDE"]
    ["ABCDE", "AB", "CD", "ADE", "XYZ", "XYZ", "ACD"]	[2,3,5]	["ACD", "AD", "ADE", "CD", "XYZ"]
    ["XYZ", "XWY", "WXA"]								[2,3,4]	["WX", "XY"]

    I/O例説明


    I/O例#1
    問題の例.
    I/O例#2
    ADを3回、CDを3回、ACDを2回、ADEを2回、XYZを2回注文しました.
    1人が5品を注文したが、少なくとも2人以上が1品を注文したため、新しい5品は追加されない.
    I/O例#3
    WX 2回とXY 2回注文しました.
    3名様とも単品メニューを3つご注文いただいておりますが、少なくとも2名様以上のお客様がご注文いただいた料理はセット後のみとなっておりますので、3品のセットは追加されません.
    また、4つ以上の単品メニューを注文したお客様がいないため、4つの料理からなるコースを新たに追加することもありません.

    方法


    この問題はitertoolsの組合せを用いてcourseのすべてのサイズの組合せを求め,defaultdict()型をcourse長のリストに入れて長さ管理を行う.長さで区切られたdefaultdict()では,個数を1増やして総回数を求めた後,最大値などの問題をそれぞれ正解リストに入れて解決する.WX,XWなど順序が異なる場合には識別が異なるためdefaultdict()に適用する前にソート適用した.
  • 正解のリスト回答を保存すると発表した.
  • の結果を保存するリストセットにdefaultdict(int)を入れ、courseの長さとして宣言します.
  • オーダーを巡回発注します.
    ->courseの長さが繰り返されるiのfor文.
    -->一時リストtmpをコンビネーション(order,course[i])のリストとして宣言します.
    -->tのfor文を回してtmpを巡る.
    ----->set[i]['.join(ソート済み(リスト(t)]を1増加します.
  • courseのiを繰り返すfor文.
    ->sets[i]が空の場合は、次の繰り返しに移動します.
    ->mxをsets[i]の最値として宣言します.
    ->sets[i]のkey,valueのfor文.
    -->valueがmx以上の場合、valueは2以上です.
    ----->回答にキーワードを入力します.
  • 昇順で
  • の答えを並べます.
  • の答えを返します.
  • solution.py

    import itertools
    import collections
    def solution(orders, course):
        answer = []
        sets=[collections.defaultdict(int) for _ in range(len(course))]
        for order in orders:
            for i in range(len(course)):
                tmp=list(itertools.combinations(order, course[i]))
                for t in tmp:
                    sets[i][''.join(sorted(list(t)))]+=1
        for i in range(len(course)):
            if not sets[i]:
                continue
            mx=max(sets[i].values())
            for key, value in sets[i].items():
                if value>=mx and value>=2:
                    answer.append(key)
        answer.sort()
        return answer