[Swift|プログラマーLv.2]メニュー更新(2021 KAKAO BLIND RECRUITMENT)


質問する
問題の説明
レストランを経営するスカフィーは、コロナ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例
    orderscourseresult["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つの料理からなるコースを新たに追加することもありません.
    に答える
    他人の解答
    import Foundation
    
    func solution(_ orders:[String], _ course:[Int]) -> [String] {
        var orderDict = [String:Int]()
        var countDict = [Int:[(String,Int)]]()
    
        var temp = [String]()
        // 주문한 메뉴들(target)로 코스요리 조합하는 함수
        func combination(_ target : [String], _ idx : Int, _ count : Int , _ limit : Int ) {
            if count == limit {
                let s = temp.reduce("", +)
                orderDict[s] = orderDict[s] == nil ? 1 : orderDict[s]!+1
                return
            }
    
            for i in idx..<target.count {
                temp.append(target[i])
                combination(target, i+1, count+1, limit)
                temp.removeLast()
            }
        }
    
        // 코스 요리 개수별 (첫 번째 for문)
        // 손님이 주문한 메뉴들로 코스요리 조합하기 (combination 함수)
        for limit in course {
            for order in orders {
                let sortedOrder = order.map{String($0)}.sorted()
                combination(sortedOrder, 0, 0, limit)
            }
        }
    
        // 주문이 2번 이상된 메뉴만 다루기 (filter)
        orderDict.filter{$0.value >= 2 }.forEach{
            // 메뉴수 별로 countDict에 값 넣기
            if countDict[$0.key.count] == nil {
                countDict[$0.key.count] = [($0.key,$0.value)]
            }else {
                countDict[$0.key.count]!.append(($0.key,$0.value ))
            }
        }
        
        var answer = [String]()
        for limit in course {
            if countDict[limit] != nil {
                // 주문수가 높은 순으로 정렬
                let list = countDict[limit]!.sorted(by: {$0.1 > $1.1})
                // 제일 많이 주문된 메뉴 구성을 answer 배열에 넣기
                answer.append(contentsOf: list.filter{list.first!.1 == $0.1}.map{$0.0})
            }
        }
    
        return answer.sorted(by: <)
    }
    正確性試験正確性試験1〉合格(0.50 ms,16.6 MB)試験2〉合格(0.65 ms,16.3 MB)試験3〉合格(0.69 ms,16.8 MB)試験4〉合格(0.96 ms,16.5 MB)試験5〉合格(0.62 ms,16.7 MB)試験6〉合格(1.56 ms,16.4 MB)試験7〉合格(1.61 ms,16.6 MB)試験8〉合格(12.05 ms,16.8 MB)試験10〉合格(6.81 ms,16.7 MB)試験11〉合格(5.10 ms,16.7 MB)試験12〉合格(6.46 ms,16.8 MB)試験13〉合格(8.94 ms,16.5 MB)試験14〉合格(8.86 ms,16.7 MB)試験15〉合格(9.24 ms,16.7 MB)試験16〉合格(3.00 ms,16.3 MB)試験17〉合格(5.80 ms,16.6 MB)試験18〉合格(16.25.41 ms,16.2 MB)試験19〉試験20〉合格(7.14 ms,16.8 MB)
    整理する
    目標解決時間:1時間
    物理プール時間:2時間2分(破棄)
    正解率:25.40%
    この問題は,2021年のKACAの新規開発者公募第1回コードテストで提起された問題である.
    試験は全部で7問を出題し、5時間以内に順序にかかわらず、問題を解決しなければならない.
    これは7問のうち2問目で、難易度の低い問題です.
    問題を解く
    リファレンス
    まず、質問の答えを得る前に、各メニューに基づいて可能なすべての組み合わせを作成してください.例えば、「ABCD」には11種類の組み合わせがあります.
  • “AB”, “AC”, “AD”, “BC”, “BD”, “CD”, “ABC”, “ABD”, “ACD”, “BCD”, “ABCD”
  • 各メニューに可能なすべての組合せを作成した場合は、各組合せの数を計算するだけです.この場合は「ABC」と「CBA」の数を同じ組み合わせにすることに注意しましょう.簡単な解決策は、まず各文字列をアルファベット順に並べたり、作成した組合せ文字列を並べ替えたりすることです.
    各組合せをカウントした場合は、文字列の長さが同じ組合せで最も多く表示される組合せを見つけることができます.
    ポスト
    難しすぎます...
    ディック・シャナリーで解けると思いますが、どうやって解けるか分かりません.(最終的に解けて諦めました…)
    正解率から見ると、他の人も答えにくいと思っています.
    ソートが複雑すぎて難しいです.ううう
    もっと問題を作って親しくなるしかない.