チームは毎朝誰かがクロワッサンをみんなのために持ってくるべきだと決めました。毎回同じ人である必要はないので、次の順番を決定するシステムが必要です。この質問の目的は、クロワッサンを明日持ってくる順番を決定するためのアルゴリズムを決定することです。
制約、仮定、目的:
これは実際の問題のモデルであるため、シナリオをより適切にモデル化していると思われる場合は、仮定に挑戦または調整することができます。
起源1: クロワッサンを買う人を見つける フロリアン・マーゲインによる。
オリジン2: クロワッサンを購入する人を見つける ジル氏。
この質問はGillesと同じバージョンであり、さまざまなコミュニティがプログラミングの課題にどのように対処しているかを確認する実験として、プログラマに再投稿されています。
スコアリングアルゴリズムを使用します。各人はゼロのスコアから始まります。クロワッサンを持参するたびに、スコアを1ずつ増やします。クロワッサンを持参しなかったすべてのチームメンバーのスコアは、1/Nずつ減少します。したがって、スコアが0の場合、チームメンバーは買いすぎでも買いすぎでもありません。
ランダム性がない場合、出席する人のリストからスコアが最も低い人を選択します。
ランダム性を追加するには、リストをスコアで並べ替え、スコアが負のすべてのチームメンバーのリストからランダムに選択します。負のスコアに制限することにより、何週間も「幸運」になることがないようにします。
このアルゴリズムの利点は、履歴記録の保持に依存せず、いつでも新しいチームメンバーを簡単に追加できることです。
クロワッサンを楽しむために存在する人だけのスコアを減らすことにより、比較的一般的な欠席を可能にするように適合させることができます。
私がこれを選ばなければならないなら、帽子を手に入れ、小さな紙にみんなの名前を一度帽子に入れます。それから毎日、帽子から誰かの名前をランダムに描きます。それが翌日クロワッサンを持ってくる人です。その紙は、「BRINGING CROISSANTS TOMORROW」の下のボードに貼り付けられます。現在ボード上にある紙は捨てられます。
箱も欲しいです。空から始まります。毎日、名前を描く前に、箱の中身を帽子に捨てて、帽子の中の書類を調べて、明日欠席する人を全員削除しました。それらの名前はボックスに入れられます。
名前を描くときが来て、帽子が空の場合は、もう少し紙をはがして全員の名前を一度追加してから、明日欠席する全員の名前をボックスに移動します。
これらの最後の2つのステップのために、同じ名前が一度に複数回ハットに入る可能性があります。たまたま描いた名前がボードに書いてある名前と同じなら、その紙を箱に移してもう一度描きます。
このシステムを選択した言語のアルゴリズムに変換することはそれほど難しくないはずです。
アルゴリズム、誤解。 DBを使用します。
create table team_members
(
id integer auto_increment,
name varchar(255),
purchase_count integer,
last_purchase_date datetime,
present integer,
prefers_donuts integer default 0,
primary key( id)
)
誰が買うの?
select id from team_members where (present = 1) and (prefers_donuts = 0) order by purchase_count, last_purchase_date limit 1;
彼らが購入した後:
update team_members set purchase_count = purchase_count + 1, last_purchase_date = now() where id = ?
次に設定します:
insert into team_members (name, prefers_donuts) values ('GrandmasterB', 1);
...私は古い学校だからです。
最初のクエリを微調整することによって少しランダム性を追加することはそれほど難しくありません。おそらく、last_purchaseの日付で並べ替えるのではなく、random()を追加します。
私は実際にこの問題を現実の世界でいくらか解決しなければなりませんでした:
remember how many times people have gotten donuts
every day:
var candidates = everyone
toss out people who aren't here tomorrow
toss out people who aren't here today
toss out the person who got them today (unless they're the only one left)
toss out everyone where "times they got donuts"/"times everyone has got donuts"
is more than 1/number of people (unless that would eliminate everyone)
pick someone at random from the candidates
何が起こるかというと、「あまりにも多く」ドーナツを購入した人(不運のため、他の人が休暇中に仕事に行くなど)は、十分な買収が行われて「正しい」パーセントに戻されるまでプールから除外されます。購入。
これは、新しい人々を雇うことをよりうまく処理するために拡張する必要があります...
とにかく、この設計は、変数を変更する(誰が参加しているか、誰が参加していないか)およびスケジュールを(実質的に)無限にする必要がある場合に非常にうまく機能しました。追加のボーナスとして、RNGをシードすることで決定論を簡単に作成できます。
すでに提示された他のいくつかの回答ほど良くはありませんが、問題を見る別の方法:
午後ごとに、次の利用可能なクロワッサンブリンガーを選択します。毎朝、クロワッサンブリンガーはリストのトップから名前を消します。
毎日の処理はペンと紙で簡単です。
新入社員 & 終了 卒業生はおそらく新しいリストを作ることによって最もよく扱われるでしょう。 CPUサイクルが再び高額になる場合(または、1億人の従業員と第1世代のArduinoしかいない場合)、元のリストに適切な数のプレースホルダーを追加するのは簡単です。
詳細(リクエストごと)。
このアプローチを任意の長いリストで使用すると、透明性のメリットが得られます。
誰が明日クロワッサンを持ってくるか知っているだけでなく、誰が翌日にクロワッサンを持ってくる予定か知っています。もちろん、時間が経つにつれて、不在などにより、精度が低下します。
紙片を帽子に入れて重みを付ける方法を理解している卑劣な開発者は、クロワッサンを運ぶ義務を回避する機会があまりありません。
処理済みであると主張する非開発者がうなり声を上げると、データを簡単に確認し、間違った結論を導き出し、とにかく駄々をこねることができます。
非ランダム
順序付きリストを維持します。購入予定の日に不在の場合は、次に空いている人と入れ替えます。結局、その人は立ち会って、クロワッサンを買うでしょう。したがって、リストの内容は同じままですが、不在によっては人が移動したり上下したりする場合があります。
新しい人は現在の位置の後にリストに挿入されます。終了または終了した人はリストから削除されます。現在位置は毎日1ずつ増加し、最後に達すると最初に戻ります。
これは、公平性を促進するための平均不在時間を説明するのに十分な人数がリストに含まれていることを前提としています。
ランダム
短期的なバイアスがあるため、毎日ランダムな人々を選択することはできません。たとえば、コインを10回めくると、ヘッド8とテイル2が出てきて、短期的に頭がねじ込まれる可能性があります。そのため、公平に保つために人々のバケットを作成する必要があります。
バケットは、ユーザーが過去にcrossiantを購入した回数によって決まります。したがって、この場合は、人と国境を越えた購入の辞書を保存します。 1日目、全員がバケット0にいます。人がクロワッサンを購入すると、次のバケツ、つまり1、2などに割り当てられます。ランダムな部分は、バケツにいる利用可能な人のプールから選んでいます。最初に利用可能なバケットは、購入数が最も少ないものです。バケツに10人いる場合は、1〜10の乱数とクロワッサンを購入する人を選びます。新しい人々は現在の最低のバケツを割り当てられているので、彼らは余分な数の交差点を購入することになりません(彼らはすぐに購入プールにいますが)。最も低いバケットで誰も利用できない場合(それらはすべて存在しない)、次に高いバケットに移動します。たとえば、10人のリストがあるとします。 8日目に、バケット1には8人、バケット0には2人が入っています。バケット0の2人は欠席しています。この場合、バケット1が使用され、最終的に1人がバケット2になります。しかし、バケット2にいる人はおそらくいないため、人々は常に相互に数クロスバイン(バケット)内にいます。しばらくの間購入プール。
微調整を追加して、同じ人物が2日間続けて購入しないようにしたり、処理するEdgeケースをいくつか用意したりすることができますが、これにより、ランダム性の要素が追加され、公平性が保たれます。また、実際のクロワッサンの購入と現在のバケツを分けておくこともできます。人が去ると、永続的に不在としてマークするか、完全に削除することにより、バケットから削除されます。