Дізнайтеся, чия черга - купити круасани


9

Команда вирішила, що кожного ранку хтось повинен приносити круасани для всіх. Це не повинно бути однаковою людиною кожен раз, тому повинна бути система, яка визначає, чия черга наступна. Мета цього питання - визначити алгоритм для вирішення, чия черга буде завтра принести круасани завтра.

Обмеження, припущення та завдання:

  • Чия черга принести круасани, буде визначено попереднього дня.
  • У будь-який день деякі люди відсутні. Алгоритм повинен вибрати когось, хто буде присутній в той день. Припустимо, що всі прогули відомі за день заздалегідь, тому покупця круасанів можна визначити в попередній день.
  • В цілому більшість людей присутні в більшість днів.
  • В інтересах справедливості кожен повинен купувати круасани стільки разів, ніж інші. (В основному, припустимо, що кожен член команди має однакову суму грошей, щоб витратити на круасани.)
  • Було б непогано мати якийсь елемент випадковості або хоча б сприйняти випадковість, щоб полегшити нудьгу реєстру. Це не важке обмеження: це скоріше естетичне судження. Однак одну і ту ж людину не слід обирати двічі поспіль.
  • Людина, яка приносить круасани, повинна знати заздалегідь. Отже, якщо людина P має принести круасани в день D, то цей факт слід визначити в якийсь попередній день, де присутня людина P. Наприклад, якщо приношення круасана завжди визначається напередодні, то це має бути одна з осіб, які були присутніми напередодні.
  • Кількість членів команди досить мала, що ресурси для зберігання та обчислення фактично необмежені. Наприклад, алгоритм може спиратися на повну історію того, хто приніс круасани, коли раніше. До декількох хвилин обчислень на швидкому ПК кожен день було б нормально.

Це модель реальної світової проблеми, тому ви можете оскаржувати або уточнювати припущення, якщо ви думаєте, що вони краще моделюють сценарій.

Походження: дізнайтеся, хто збирається придбати круасани від Флоріана Маргайна . Моє переформулювання тут має дещо інші вимоги.


1
Про що саме було питання? Чи можемо ми припустити, що люди відсутні в більшій чи меншій мірі однакової кількості? Що поганого в тому, щоб прийняти людину, яка це зробила найменше, чи просто випадкову людину?
Pål GD

@ PålGD Якщо припустити, що люди відсутні приблизно на стільки ж, було б спрощенням. Робіть це, якщо хочете, але якщо ваш алгоритм працює за таймерами, це краще. Взяти людину, яка зробила це найменше разів, - це одне рішення (хоча пам’ятайте про те, що вони знають за один день заздалегідь, це робить рішення не зовсім банальним). Випадкова людина також може працювати, але випадковість вводить відхилення від справедливості, до яких ви можете зв'язатись.
Жил "ТАК - перестань бути злим"

Що? Немає слинової картини? Ви хочете, щоб ми невільниці за нашим столом займалися математикою, а не вислизали до пекарні?
Калеб

@Gilles - FYI, проводячи експеримент на P.SE зі своєю версією цього питання . Тепер, коли обидва сайти трохи старші, мені цікаво побачити, як формуються відповіді кожної громади.

Відповіді:


7

Існує дві категорії рішень цієї проблеми, про які я знаю: упереджені лотереї та відфільтровані / генеровані випадкові послідовності .

По-перше, давайте не обходимося з легкими, але неправильними рішеннями, які не мають стану. Будь-яке рішення в стилі лотереї, яке не підтримує жодного стану, матиме кількість виграшів у біноміальному розподілі, що не відповідає критерію "стільки разів". Ви можете обрати випадкову послідовність, яка підбирає всіх людей однаково (просто це обійде список; перестановки забезпечують випадковість), але як тільки люди почнуть їхати у відпустку, у вашій послідовності тепер є дірки. Якщо ви не стежите за цим, ви знову опинитесь з біноміальними розподілами замість підтримки рівних зусиль.

Давайте також беремо на себе фактичну випадковість. Ви можете цього захотіти, щоб, наприклад, людина не змогла запланувати свою відпустку на основі детермінованого алгоритму, щоб вони ніколи не були присутніми, коли настала їх черга купувати круасани (я думаю, поки вони не використають усі дні своїх відпусток) .

Отже, на два типи рішень.

  1. Щоб побудувати упереджену лотерею, спершу зауважте, що ми можемо вибрати майже будь-який безперервний розподіл (з кінцевим відхиленням), щоб генерувати номери для нашої лотереї. Тоді програш може бути людиною з найнижчою кількістю. Тоді найпростіша упередженість - це відслідковувати, чи купила кожна людина більше чи менше своєї частки. Ви можете виміряти зміщення в одиницях круасанів. Ви можете налаштувати ступінь випадковості, змінивши ширину та форму розподілу - це також визначить, наскільки далеко може потрапити будь-яка людина з "однакової кількості разів". Гаусианці легкі; вони допускають розумний сюрприз, не маючи занадто довгих хвостів ("несправедливих"). Отже, основна форма рішення (в коді Scala)

    case class Employee(var bias: Double) {
      def eat         { bias -= 1 }
      def buy(n: Int) { bias += n }
      def roll        = bias + stdev * Random.nextGaussian
    }
    

    Ви можете відслідковувати, хто купував останній, і давати їм здоровий бонус за ухил (наприклад 10*stdev), щоб люди не купували двічі поспіль, економити у кращому випадку, коли структура відпусток дозволила кожному купувати "останній" час. (тобто ви купуєте, потім вирушайте у відпустку.) Те саме, що ви не присутні в день, коли вони обрані. (Якщо хтось відсутній через день, він, зрештою, з’явиться , коли згоряє через свій бонус за упередженість; я вважаю це особливістю, а не помилкою)

    Отже, ви збираєте свій список присутніх співробітників за день, пропонуєте їм усіх розіграти на лотерею, виберіть найнижчого та оновите. Ви можете вибрати, чи повинен бонус за покупку дорівнювати кількості працівників (добре, коли вартість незначна, але поїздка на круасани обтяжлива), кількість присутніх працівників (добре, якщо поїздка легка, але вартість обтяжлива. ), або щось середнє (визнати обидва тягарі). Напевно, краще лише наказати "їсти" людям, які є присутніми, але ви можете це зробити в будь-якому випадку, якщо відчуєте, що просто перебування у відпустці не дає вам кращого кроку менше.

  2. Щоб побудувати відфільтровану випадкову послідовність, спочатку потрібно сформувати випадкову послідовність. Переміщення списку працівників - так само хороший спосіб, як і будь-який. Просто перегляньте список, по порядку, з дня на день. Якщо хтось не може придбати, оскільки він відсутній або не може бути сказаний чи куплений раніше, пропустіть їх. Тепер у вас є проблема: ви накопичуєте людей, яких пропустили. Це все гаразд. Коли ви закінчите свою послідовність, додайте список пропущених співробітників до повного списку перед переміщенням. Тепер вірогідність появи пропорційна кількості разів, яку ви пропустили, що підтримує властивість "стільки ж разів".

    Якщо ви використовуєте стандартні перетасування, також особливо легко оцінити випадковість, коли відпусток немає. Якщо ви обираєте людей абсолютно випадковим чином, знання про те, кого слід принести далі, містили бlog2(N) шматочки інформації, якщо вони були Nслужбовців. Натомість, однак, лишеN! замість NN можливі послідовності дозволені, тому інформація зменшується на log2[(N!NN)1/N]1log(2)+log22π/NN1.4 біт (для великих N; дляN=10 його  1.14).

Особисто я віддаю перевагу упередженому лотерейному рішенню, оскільки контроль над випадковістю кращий. За допомогою відфільтрованих послідовностей ви можете придумати більш складні способи генерування послідовностей. Наприклад, замість того, щоб робити випадкову перестановку, виконувати локальні заміни на певну відстань або дозволяти повністю замінювати людей з пулу (але вони йдуть у список, який пропустили), але ці речі вимагають більше алгоритмічних зусиль. За допомогою лотереї ви просто коригуєте стандартне відхилення.


4

Дозволяє {P1,...,Pn}бути безліччю байок круасана. Дозволяєvik1 бути витраченою сумою Pi на круасани до дня k(це може бути кількість разів, коли він купує круасани, якщо вони завжди витрачають одні й ті ж гроші, незалежно від кількості присутніх народів, які не виглядають досить розумними для нашого любителя круасанів); то1 призначена для ініціалізації та уникнення поділу на 0.

Для деякого параметра l, дозволяє vk=i=1n(vik)l.

У день k, вони вибирають покупця круасана наступного дня, запускаючи випадкову змінну, яка є результатом i з вірогідністю 1(vik)lvk. Якщо вибраного немає тут (сьогодні чи на наступний день), вони кидають монету ще раз, поки не знайдуть підходящу (вона все-таки існує, тому що вони здебільшого тут щодня ...).

І вони жили щасливо, поки не дізналися про це P1, той боягуз, був там, тільки один день за два, і так, ніколи не купує жодного круасана!

Після деякого роздуму (і може бути трохи катування на P1 щоб він повернув круасан, який він їв, не плативши) вони змінюють свій алгоритм.

Вони обчислюють середню ціну круасану, яку вони платять щодня, і називають це v.

У перший день вони розраховують планування покупців на наступні дні. Для цього вони роблять, як і раніше, із випадковою змінною та оновленнямvik за ціною, яку вони повинні були заплатити в день k, тобто додавання vщоразу, коли планується йти до пекаря. Оскільки вони розумні і не хочуть платити занадто багато, вони також пам’ятають, скільки вони насправді платили за деньk так що коли вони оновлять планування, ніхто не буде покараний.

Вони планують, поки кожен Pi у майбутньому є дата, де він повинен купити круасан.

Якщо Pi планували купувати круасани на день k+1 але оголошує, що не може в день k (або якщо він не був утеплений) він віддає своє місце комусь із присутніх, які не мають зобов'язань наступного дня, наприклад Pj і він приймає наступну чергу Pj.

День, коли перший із Pi не планується купувати круасани в майбутньому, вони продовжують своє планування (з випадковою змінною, обчисленою з vik оновлено до реальної суми, яку вони заплатили, і запланованої суми), поки всі не повернуться до черги.

І коли це відбувається назавжди, вони живуть щасливими, поділяючи порівну ціну круасану.

Але P1не задоволений. Дійсно, він вважає, що обранийlзанадто мала, тому ймовірність виплати двічі поспіль занадто велика. Що б там не було ... Інші дозволяють йому обиратиlстільки, скільки він хоче. Оскільки він бурхливий, але не дурний, він вибравl=k таким чином проходить час, навіть якщо співвідношення між великими платниками та дрібними гравцями, як правило, не бачиться великим l схильні це підкреслювати.

Все-таки P1 не такий щасливий, він там лише половину днів (так половина круасана) і повинен платити стільки, скільки P2що є тут щодня. Недобросовісно!

Але тому, що вони втомилися від бурчання P1, вони ганяють геть. Але в кутку голови вони все ще думають змінитиvik в різниці між тим, що вони заплатили, і тим, що вони їдять (нормалізується для отримання позитивних значень), але вони занадто ледачі і занадто повні круасанів.

Пс: Вибачте за погану англійську мову, але я не є носієм мови, і пізно ... будь ласка, виправляйте помилки (і, можливо, додайте сюди спецій до історії ...)


2

Кожна ітерація у вас є

  • Список людей, які присутні і доступні для придбання
  • Попередній покупець

Якщо ви вибрали людину випадково серед людей у ​​списку та виключили попереднього покупця, ви досягнете своїх цілей:

  1. Алгоритм є "максимально" випадковим, оскільки ми використовуємо мінімальну кількість інформації з попередньої ітерації та вибираємо випадковим чином.
  2. В середньому люди платять за (N / (N-1)) круасани кожного разу, коли вони беруть участь у видобутку, роблячи алгоритм максимально справедливим.
  3. Я б запропонував усунути правило без повтору, щоб зробити це максимально випадковим.

Інші алгоритми, які я бачив, пропонуються менш випадковими або менш справедливими:

  1. Алгоритми "переміщення колоди" насправді не випадкові в тому сенсі, що ймовірність заплатити не є постійною (1 / N у першому виборі, 1 / (N-1) у другому ... 1 при N-му виборі - - якщо його ще не вибрали). Крім того, якщо вас обрали першими, ви маєте рівно нульові шанси бути вибраними протягом наступних N разів. Система легко руйнується, потрапляючи рідко, доки не вибирається, а потім постійно.

  2. "Компенсаційні" алгоритми, які намагаються активно змусити всіх отримувати однакову кількість круасанів, замість того, щоб покладатися на властивості випадкових чисел, не можуть бути випадковими або справедливими (або обома).


З N людей і m працівників, присутніх в середньому за день, відхилення в кількості разів буде приблизно N/m. Оскільки існують рішення, які ніколи не відхиляються більше1, це дивне визначення поняття "справедливий" (тим більше, що було вказано як "стільки разів").
Рекс Керр

Nпокупки, звичайно, не люди.
Рекс Керр

@RexKerr Чому б ти купував більше круасанів, ніж співробітників?
Sklivvz

Я збентежений. Де я запропонував би одного?
Рекс Керр
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.