Дізнайтеся, чия черга - купувати круасани, враховуючи можливі прогули


13

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

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

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

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


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


2
Додано повідомлення про публікацію, я буду захищати, якщо це потрібно, але я хотів би тримати його максимально відкритим, доки можу. Зважаючи на те, що це питання є якоюсь складним, це експеримент. Він залишиться відкритим. Для науки!
Світовий інженер

4
Більше підходить для Code Golf?
ozz

3
Кого хвилює? Жодна поважаюча себе команда не мала б круасанів. Тепер пончики , з іншого боку, це цікаве питання.
Росс Паттерсон

3
Це звучить як ідеальний випадок використання форми DA 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
Я думаю, що ваш останній абзац є важливим, інакше хтось, хто їде у відпустку на місяць (можливо, медовий місяць), повернеться до величезних негативних результатів та багато покупки.
Джеймс

8
Може також підправити: -1, якщо ви їсте тістечко, яке приніс хтось інший. (N-1), якщо ви купуєте випічку. Таким чином, якщо комусь пощастить і купує лише за 4, то наступного дня людина отримує невдачу і купує за 7, ці два покупки не ставляться однаково. -1 бо випічка, яку ви купуєте для себе, нейтральна.
Джеймс

@James, без страху; ОП у США, і ніхто в США не потрапляє ніде поблизу такої відпустки. :(
Kyralessa

@James Так, це хороше поліпшення.
Gort the Robot

7

Що я б робив, якби мені довелося це вибрати, - це отримати шапку і покласти один раз імена кожного в шапку на маленькі шматочки паперу. Тоді кожного дня я б навмання малював чиєсь імені з шапки, і це людина, яка принесе круасани наступного дня. Потім цей папір потрапляє на дошку під заголовком "ВЗАЄМО ЧАС КРОЙСАНТІВ". Папір, який зараз знаходиться на дошці, викидається.

Я також мав би коробку. Він починається порожнім. Кожного дня, перш ніж малювати імена, я скидаю вміст коробки в шапку, потім перебираю папери в шапці і видаляю всіх, хто завтра відсутній. Їх імена містяться в коробці.

Якщо прийшов час намалювати ім’я, а шапка порожня, я зірву ще трохи паперу та додаю ім’я кожного разу, а потім перенесіть імена всіх, хто завтра відсутній, у поле.

Через ці два останні кроки одне і те ж ім’я може бути в капелюсі кілька разів одночасно. Якщо ім’я, яке я малюю, те саме, що ім'я на дошці, я переміщу цей папір у коробку, а потім намалюю ще раз.

Перекласти цю систему в алгоритм не слід занадто складно на обраній вами мові.


Розбирання капелюха для всіх, хто вийде на вулицю, здається справжнім болем.
Бобсон

@Bobson: У питанні конкретно сказано, що чисельність команди порівняно невелика. Якби я мав справу з великим набором даних, я б зробив щось більш складне.
Мейсон Вілер

6

Алгоритм, smalgorithm. Використовуйте БД.

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.


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. Дублювати список багато разів (скажімо, 1000)
  3. Перемішайте список

Кожного дня оберіть наступний доступний круасан-приноситель. Кожного ранку приноситель круасану перекреслює своє ім’я вгорі списку.

Щоденна обробка ручкою та папером проста.

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


Детальніше (за запитом).

Використовуючи такий підхід із довільно довгим списком, ви отримуєте перевагу прозорості.

Ви не тільки знаєте, хто завтра принесе круасани, ви знаєте, хто планує привезти їх на наступний день тощо. Звичайно, чим далі вчасно ви виглядатимете менш точними, ви будете через прогули тощо.

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

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


1
Припинення ? Ghenghis Khan схвалює цю посаду.
Мисливець на оленів

1
@DeerHunter Мені завжди не подобалося, як HR говорить про "припинення людей". Це доводить до уваги стрілянину. Можливо, я повинен був би сказати "Нові наймачі та випускники ...".
Dan Pichelman

1

Не випадкові

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

Нові люди вставляються до списку після поточної позиції. Люди, які вийшли або припинили роботу, вилучаються зі списку. Зростання поточної позиції на 1 щодня, коли вона досягне кінця, вона повернеться до початку.

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

Випадкові

Ми не можемо просто вибирати випадкових людей щодня, оскільки буде короткострокове зміщення, наприклад, переверніть монету в 10 разів, і ви можете підійти до голови 8 і хвостиків 2, так що голови будуть накручені на короткий термін. Отже, нам потрібно створити відра людей, щоб це було справедливим.

Відро визначається тим, скільки разів люди купували кросіанти в минулому. Отже, у цьому випадку ми б зберігали словник людей та перехресних покупців. У перший день усі в ковші нульові. Коли люди купують круасани, вони будуть призначені на наступне відро, тобто на 1, 2 і т. Д. Випадкова частина збирається з пула доступних людей у ​​відрі. Перше доступне відро - це найменше покупців. Якщо у відрі є 10 людей, то виберіть випадкове число від 1 до 10 і того, хто купує круасани. Новим людям присвоюється найнижчий відрізок, щоб вони не закінчили купувати додаткові патрони (хоча вони будуть відразу в пулі). Якщо нікого немає в найнижчому відрі (вони всі відсутні), тоді ви переходите до наступного найвищого відра. Наприклад, s скажімо, є список з 10 осіб. 8-го дня 8 відра перебувають у відрі 1, а 2 - у відрі 0. Двоє людей у ​​відрі 0 відсутні. У цьому випадку використовуватиметься відро 1, і одна людина потрапить у відро 2. Але люди завжди будуть знаходитись у кількох перехідних покупках (відрах) всередині одного, оскільки людина, яка зараз знаходиться у відрі 2, швидше за все, не буде купуйте басейн на деякий час.

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


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