欠席の可能性を考慮して、誰の番がクロワッサンを購入するのかを調べます


13

あるチームは、毎朝誰かがクロワッサンを持参することを決めました。毎回同じ人物であってはならないので、次の順番を決定するシステムが必要です。この質問の目的は、明日クロワッサンを持ち込む順番を決定するアルゴリズムを決定することです。

制約、仮定、目的:

  • クロワッサンを持参する順番は、前日の午後に決定されます。
  • ある日、欠席している人もいます。アルゴリズムは、その日に出席する人を選択する必要があります。欠席はすべて1日前にわかっているため、クロワッサンの買い手は前日の午後に決定できると仮定します。
  • 全体として、ほとんどの人はほとんどの日に出席しています。
  • 公平を期すため、誰もがクロワッサンを他の人と同じ回数購入する必要があります。(基本的に、すべてのチームメンバーがクロワッサンに費やす金額が同じであると仮定します。)
  • 名簿の退屈を軽減するために、ランダム性の要素、または少なくとも知覚されたランダム性を持つことが望ましいでしょう。これは厳しい制約ではありません。それは審美的な判断です。ただし、同じ人を連続して2回選ぶことはできません。
  • クロワッサンを持ってくる人は事前に知っておくべきです。したがって、人PがD日にクロワッサンを持参する場合、この事実は人Pがいる前日に決定する必要があります。たとえば、クロワッサンの持ち主が常に前日に決定される場合、前日にいる人の1人である必要があります。
  • チームメンバーの数は十分に少なく、ストレージとコンピューティングリソースは事実上無制限です。たとえば、アルゴリズムは、過去に誰がクロワッサンを持ってきたかの完全な履歴に依存できます。毎日高速のPCで最大数分間の計算で問題ありません。

これは現実世界の問題のモデルであるため、シナリオをより適切にモデル化していると思われる場合は、自由に仮定に挑戦したり洗練したりできます。


起源1:Florian Margaineによるクロワッサンの購入者を確認します。
起源2:がジルによってクロワッサンを買うつもりかを調べます。
この質問は、Gillesと同じバージョンであり、さまざまなコミュニティがプログラミングの課題にどのように対処するかを確認するための実験として、プログラマーに再投稿されました。


2
通知を追加しました。必要に応じて保護しますが、できる限り開いたままにしておきたいと思います。この質問が何らかの形で困難であることについては、実験です。開いたままになります。科学について!
世界エンジニア

4
コードゴルフにより適していますか?
ozz

3
誰も気にしない?自尊心のあるチームにはクロワッサンはありません。一方で、ドーナツ、それは興味深い質問です。
ロスパターソン

3
これは、DA Form 6の完璧なユースケースのように聞こえます(1974年以来陸軍で機能していました!)。使用方法については、AR 220-45をご覧ください。それをアルゴリズムに変換するのは比較的簡単なはずです。
アダムバルサム

2
(@AdamBalsam上のフォーム展開しarmypubs.army.mil/eforms/pdf/A6.PDFと使用apd.army.mil/pdffiles/r220_45.pdfを ...そして私の元雇用にこれを提案しないでください、彼ら十分なポリシーと手順がそのままある)

回答:


26

スコアリングアルゴリズムを使用します。各人はゼロのスコアから始まります。クロワッサンを持ち込むたびに、スコアを1ずつ増やします。クロワッサンを持ち込まなかったすべてのチームメンバーのスコアは、1 / Nずつ減少します。したがって、スコアが0の場合、チームメンバーは買われ過ぎも買われていないことも意味します。

ランダム性がない場合は、出席する人のリストからスコアが最も低い人を選択します。

ランダム性を追加するには、スコアでリストをソートし、負のスコアを持つすべてのチームメンバーのリストからランダムに選択します。負のスコアに制限することで、何週間も「幸運」にならないようにします。

このアルゴリズムの利点は、履歴記録の保持に依存せず、いつでも新しいチームメンバーを簡単に追加できることです。

クロワッサンを楽しむために出席者だけのスコアを減らすことで、欠席が比較的一般的であることを考慮に入れることができます。


3
最後の段落は必須だと思います。さもなければ、1か月間休暇をとる人(ハネムーンかもしれません)が大きなネガティブスコアに戻って、多くの買い物をします。
ジェームズ

8
微調整することもできます:他の人が持ってきたペストリーを食べると-1 (N-1)ペストリーを購入する場合。そうすれば、誰かが幸運になり、4だけを購入した場合、翌日、その人は不運になって7を購入し、これら2つの購入は同等に扱われません。-1自分で購入するペストリーは中立であるため。
ジェームズ

@ジェームズ、恐れない。OPは米国にあり、米国の誰もそのような休暇に近づきません。:(
キラレッサ

@ジェームズええ、それは良い改善です。
ロボット

7

これを選択しなければならなかった場合、私は帽子を手に入れ、小さな紙の上に全員の名前を帽子に一度入れます。それから毎日、帽子から誰かの名前をランダムに引き出します。それが翌日にクロワッサンを持ってきた人です。その紙は、「明日をもたらすクロワッサン」の下で、ボードに貼り付けられます。現在ボードにある紙は捨てられます。

私も箱を持っていました。空から始まります。毎日、名前を描く前に、私は箱の中身を帽子に捨てて、帽子の書類を調べて、明日欠席する人を全員削除します。彼らの名前は箱に入っています。

名前を書き、帽子が空になったら、もう少し紙を取り除いて全員の名前を一度追加し、明日欠席する全員の名前をボックスに移動します。

これらの最後の2つのステップにより、同じ名前が一度に複数回ハットになる可能性があります。たまたま描いた名前がボード上の名前と同じである場合、その紙を箱に移動してから再度描画します。

このシステムを選択した言語のアルゴリズムに変換するのはそれほど難しくないはずです。


外出するすべての人のために帽子を並べ替えることは、本当の苦痛のように思えます。
ボブソン

@Bobson:この質問は、特にチームの規模が比較的小さいと言っています。大規模なデータセットを扱っていた場合は、もっと高度なことをします。
メイソンウィーラー

6

アルゴリズム、smalgorithm。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()を追加することによって。


1
+1。新規採用の場合、purchase_count他の全員の平均に初期化しますか?
ダンピチェルマン

6
うーん、とても良い質問です。それはおそらくうまくいくでしょう。または、新しい男が毎朝クロワッサンを持ってきて、追いつくまで待つこともできます。彼は結局新しい男です。
GrandmasterB

4

私は実際にこの問題を現実世界でいくらか解決しなければなりませんでした:

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をシードすることで決定論を簡単に作成できます。


2

すでに提示されている他の回答のいくつかほど良くはありませんが、問題を見る別の方法:

  1. 参加している全従業員のリストを作成する
  2. リストを何度も複製します(たとえば、1,000)
  3. リストをシャッフルする

毎日午後、次に利用可能なクロワッサンブリンガーを選択します。毎朝、クロワッサンブリンガーは自分の名前をリストの一番上から外します。

毎日の処理はペンと紙で簡単です。

新入社員&終端の卒業生は、おそらく最高の新しいリストを作ることによって処理されます。CPUサイクルが再び高くなる(または1億人の従業員と第1世代のArduinoのみ)場合は、適切な数のプレースホルダーで元のリストを簡単に調整できます。


詳細(リクエストごと)。

任意に長いリストでこのアプローチを使用すると、透明性の利点が得られます。

明日クロワッサンを持ってきてくれる人を知っているだけでなく、翌日に誰がクロワッサンを持ってきてくれるかなども知っています。もちろん、時間の先に進むと、欠席などが原因で精度が低下します。

帽子の中で紙片をどのように計量するかを考え出す卑劣な開発者は、クロワッサンを作る義務を回避する機会があまりないでしょう。

処理済みのリグを主張する非開発者は、データを簡単に確認し、間違った結論を導き出し、とにかく泣き叫ぶことができます。


1
終了?Ghenghis Khanはこの投稿を承認します。
鹿ハンター

1
@DeerHunter HRが「人を解雇する」ことについて話すのはいつも嫌いです。発砲隊を思い起こさせます。代わりに「新入社員と卒業生」と言うべきだったかもしれません。
ダンピチェルマン

1

非ランダム

順序付きリストを維持します。購入予定日に欠席している場合は、次に利用可能な人と交換します。最終的にはその人が立ち会って、クロワッサンを購入します。そのため、リストの内容は同じままですが、不在によって人が移動したり上下したりする場合があります。

新しい人は現在の位置の後にリストに挿入されます。終了または終了したユーザーはリストから削除されます。現在の位置は毎日1ずつ増加し、最後に達すると最初に戻ります。

これは、平均的な不在時間を考慮して公平性を促進するのに十分な人がリストにいることを前提としています。

ランダム

短期的な偏りがあるため、毎日ランダムな人を選択することはできません。たとえば、コインを10回フリップし、ヘッド8とテール2を上げると、短期的には頭がねじ込まれます。そのため、公平を保つためにバケットを作成する必要があります。

バケツは、人々が過去にクロシアンを購入した回数によって決まります。そのため、この場合、人々とクロシアント購入の辞書を保存します。1日目は全員がバケット0にいます。人々がクロワッサンを購入すると、次のバケツ、つまり1、2などに割り当てられます。ランダムな部分は、バケツ内の利用可能な人々のプールから選択されます。最初に利用可能なバケットは、購入数が最も少ないバケットです。バケツに10人いる場合は、1から10までの乱数と、クロワッサンを買う人を選びます。新しい人には現在の最低のバケツが割り当てられるので、彼らは最終的に余分なラウンドのクロイアントを購入することはありません(すぐに購入プールに入るでしょう)。一番下のバケットに誰もいない場合(すべてが存在しない場合)、次に高いバケットに移動します。たとえば、みましょう 10人のリストがあると言います。8日目、8人がバケット1に、2人がバケット0にいます。バケット0の2人は不在です。この場合、バケツ1が使用され、1人がバケツ2になります。しかし、バケツ2にいる人はほとんどいない可能性が高いため、人々は常に互いに数少ないクロスバイ(バケツ)内にいます。しばらくの間、購入プール。

同じ人が2日間連続で購入しないように調整を加えることもできますし、いくつかのエッジケースを処理する必要がありますが、これによりランダム性の要素が追加され、公平性が保たれます。また、実際のクロワッサンの購入と現在のバケットを分離しておくこともできます。人々が去ると、それらを完全に不在にするか、完全に削除することにより、バケットから削除されます。


1
ランダム実装を追加しました。
ジョンレイナー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.