パブリック解決:秘密のサンタ


Elvesは今日の仕事のために秘密のサンタスクリプトを作りたい.
あなたがこれを知らないならば、それは基本的に我々が名前のリストを提供するシステムです、そして、我々はランダムな人々を互いに割り当てなければなりません.
これらの人々はそれからお互いに贈り物を買わなければなりません.
彼らは私たちにいくつかの規則を与えました.
  • 誰もが秘密サンタを
  • あなたは、あなた自身の秘密のサンタでありえません
  • 重複する名前がある場合、エラーをスローすべきです
  • 秘密のサンタのランダム化する必要があります
  • You can find the puzzle here.

    解決策を考える
    これは実際にはかなり難しいものであり、私はそれを完全に順序で動作させるために私にしばらくかかった.
    主な問題は、ランダム化する必要があるということです.
    例を挙げましょう.
    以下の名前があります.Bob , Anna , Jim .
    スクリプトを実行すると、Bob , 彼の秘密サンタはAnna .
    それから我々はAnna , そして、ちょうど割り当てましょうBob .
    しかし、待って、今我々は誰にも割り当てることはできませんJim ...
    ご覧の通り、少し複雑になります.
    しかし、心配しないでください、我々は防弾するためにそれを分類します.

    でサンタを作成する
    最も簡単な仕事から始めましょう.幸運にも、名前の配列に重複する名前があればエラーをスローできます.
    if (hasDuplicates(names)) throw Error('DUPLICATE_NAMES');
    
    このhasDuplicates 関数はパズルによって提供されますが、次のようになります.
    export const hasDuplicates = (arr) => {
      return new Set(arr).size !== arr.length;
    };
    
    それから、我々はすべての名前の上でループする必要があります map method , しかし、これは1つのエッジケース(後で)をもたらすでしょう.
    だから私はで行くことにした reduce method 代わりに.
    return names.reduce((acc, name) => {
        // Todo
        return acc;
    }, []);
    
    これは基本的な縮小がどのように見えるかです.私たちはacc 基本的に前の値です.
    最初に、デフォルト値[] .
    これはすでに素晴らしいですが、我々は割り当てられた名前を追跡したい.
    私はランダムに名前をソートする関数の外側に新しい変数を作成することを決めた.
    const secretSantaNames = [...names].sort(() => 0.5 - Math.random());
    
    それから、我々はそれらの名前のうちの1つを取り戻したいです、しかし、それは我々自身の名前でありえません.
    このために、我々は単に sort method 最初のヒットを返します.
    let secretSanta = secretSantaNames.filter(
      (secretSantaName) => secretSantaName !== name
    )[0];
    
    フィルタは、我々がユーザーの減少ループ名と一致しないことを確認します.
    次の名前の秘密のサンタの配列からこの名前を削除する必要があります.
    これは素晴らしい機会です splice method .
    secretSantaNames.splice(
      secretSantaNames.findIndex((i) => i === secretSanta),
      1
    );
    

    Note: the splice method manipulates the original array!


    そして、私たちはacc 変数とプッシュこのオプションを一致します.
    acc.push({
      name,
      secretSanta,
    });
    
    右、ほとんどそこに.
    しかし、私たちが問題で説明したように、私たちがまだ割り当てられない1つの名前を持つことができたわずかなエッジケースがあります.
    これを解決するために、私たちはsecretSanta が定義されていない場合には、これを最初のマッチで交換する.

    Note: Remember I said the reduce would be easier than map. This is why.


    if (secretSanta === undefined) {
      // Edge case where last person was assigned to their own name
      // Simply swap with the first one.
      secretSanta = acc[0].secretSanta;
      acc[0].secretSanta = name;
    }
    
    秘密のサンタが未定義で、単に最初のヒットでこれを交換するならば、この機能は発射するでしょう.
    これは1つだけの名前が残っているので、動作します.
    テストを実行してみましょう.

    はい、我々はそれをやった!
    私は、あなたが私のアプローチについてどう思うか、あるいは、あなたが異なることをするのを聞きたいです.

    読んでいただきありがとうございます、接続しましょう!
    私のブログを読んでくれてありがとう.私の電子メール会報を購読して、接続してくださいFacebook or