Узнайте, чья очередь покупать круассаны

9

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

Ограничения, предположения и цели:

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

Это модель реальной проблемы, поэтому вы можете оспорить или уточнить допущения, если считаете, что они лучше моделируют сценарий.

Происхождение: Узнайте, кто собирается купить круассаны от Флориана Маргэйна . Моя переформулировка здесь имеет несколько иные требования.

Жиль "ТАК - перестань быть злым"
источник
1
Какой именно был вопрос? Можем ли мы предположить, что у людей отсутствует более или менее одинаковое количество? Что плохого в том, чтобы брать человека, который сделал это наименьшее количество раз, или просто случайного человека?
Пол Г.Д.
@ PålGD Предполагать, что люди отсутствуют примерно на столько же, было бы упрощением. Делайте это, если хотите, но если ваш алгоритм работает на неполный рабочий день, это лучше. Взятие человека, который сделал это наименьшее количество раз, является одним из решений (хотя имейте в виду, что они знают об этом за день, это делает решение не совсем тривиальным). Случайный человек также может работать, но случайность вводит отклонение от справедливости, которое вы можете захотеть связать.
Жиль "ТАК - перестань быть злым"
Какая? Нет слюнотечения? Вы хотите, чтобы мы рабыни за нашим столом делали математику, а не уходили в пекарню?
Калеб
@Gilles - К вашему сведению, проводим эксперимент на 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. Чтобы построить отфильтрованную случайную последовательность, сначала вам нужно сгенерировать случайную последовательность. Перестановка списка сотрудников - лучший способ начать. Просто просмотрите список, по порядку, изо дня в день. Если кто-то не может купить, потому что его нет или его нельзя сказать или купить раньше, пропустите его. Теперь у вас есть проблема: вы накапливаете пропущенных людей. Это нормально, хотя. Когда вы дойдете до конца своей последовательности, добавьте список пропущенных сотрудников к полному списку, прежде чем перемешивать. Теперь вероятность появления пропорциональна тому, сколько раз вы были пропущены, что поддерживает свойство «то же количество раз».

    Если вы используете стандартный случайный порядок, особенно легко определить количество случайностей, когда нет отпусков. Если вы выбрали людей , совершенно случайно, знание о том, кто должен был принести следующий будет содержать битов информации , если были N сотрудников. Вместо этого, однако, только N ! вместо N N возможны возможные последовательности, поэтому информация уменьшается на log 2 [ ( N !журнал2(N)NN!NNбита (для большогоN; дляN=10это1,14).журнал2[(N!NN)1/N]-1журнал(2)+журнал22π/NN-1.4NNзнак равно10 1,14

Лично я предпочитаю предвзятое решение для лотереи, так как контроль над случайностью лучше. С отфильтрованными последовательностями вы можете придумать более сложные способы создания последовательностей. Например, вместо случайной перестановки, выполнить локальные перестановки на определенное расстояние или разрешить выгружать людей из пула целиком (но они попадают в пропущенный список), но эти вещи требуют больших алгоритмических усилий. С помощью лотереи вы просто корректируете стандартное отклонение.

Рекс Керр
источник
4

{п1,,,,,пN}vяК-1пяК-10

LvКзнак равноΣязнак равно1N(vяК)L

Кя1-(vяК)LvК

п1

п1

v

vяККvК

пя

пяК+1КпJпJ

пяvяК

И когда это продолжается вечно, они живут счастливыми, деля одинаково цену на круассан.

п1LLLзнак равноКL

п1п2

п1vяК

Ps: извините за плохой английский, но я не являюсь носителем языка, и уже поздно ... пожалуйста, не стесняйтесь исправлять ошибки (и, возможно, добавьте такие специи в историю ...)

wece
источник
2

Каждая ваша итерация

  • Список людей, которые присутствуют и доступны для покупки
  • Предыдущий покупатель

Если вы случайно выбрали человека среди людей в списке и исключили предыдущего покупателя, вы достигнете своих целей:

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

Другие предложенные мной алгоритмы менее случайны или менее справедливы:

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

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

Sklivvz
источник
С NмN/м1
N
@RexKerr почему вы покупаете больше круассанов, чем сотрудников?
Скливвз
Я смущен. Где я предложил один будет?
Рекс Керр