Общий День Рождения

9

Офис (назовем его «Офис») сократит потраченное время в 2019 году, объединив офисные дни рождения. Любые два человека с днем ​​рождения между понедельником и пятницей (включительно) одной и той же недели будут отмечаться совместно с Днем рождения на этой неделе. Люди, чьи дни рождения выпадают на субботу или воскресенье, вообще не устраивают вечеринки.

Некоторые люди не любят делить вечеринку по случаю дня рождения с людьми, которые не разделяют их фактический день рождения. Они будут очень злы на вечеринку по случаю дня рождения .

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

Соревнование

Напишите программу или функцию, которая выводит первый номер недели ISO для 2019 года, в котором кто-то в имитируемом офисе становится очень злым по поводу своей общей вечеринки по случаю дня рождения при условии соблюдения следующих основных правил:

  • введите целое число N > 1, которое является числом работников в офисе.
  • в N дней рождения сами по себе распределены равномерно в случайном порядке с 1 января по 31 декабря (игнорировать 29 февр).
  • но рабочими неделями в целях определения общих дней рождения являются даты недели ИСО 2019, между 2019-W01-1 (2018-12-31) и 2019-W52-7 (2019-12-29). Новая неделя ISO начинается каждый понедельник. (Я думаю, что это все, что вам действительно нужно знать о неделях ISO для этого испытания).
  • для N человек в офисе у каждого есть шанс 1/3 иметь тип личности « Очень сердитый общий день рождения », так что вам придется имитировать это тоже.
  • но они не будут злиться, если вечеринку дадут людям, у которых день рождения одинаковый .
  • выведите номер недели ISO (точный формат для этого гибок, если номер недели ясен) для первого появления очень сердитого человека. Если нет злых людей, вы можете вывести все, что не перепутано с неделей ISO или программа может выдать ошибку и т. Д.

Некоторые упрощающие предположения:

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

правила

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

Пояснения к коду приветствуются.

Отработанные примеры

Придуманный пример 1 с входом N = 7. Первый и второй столбцы являются случайными, как описано в правилах (но, конечно, здесь не случайно).

Angry Type
Person?    Birthday   ISO Week   Comment
================================================================================
   N       2018-12-31      W01   In the 2019 ISO week date year 
   Y       2018-12-31      W01   Same birthday, so no anger happens
   N       2019-02-05      W06   
   Y       2019-03-15      W11   No anger happens because other W11 b-day is a Saturday     
   N       2019-03-16      W11
   N       2019-09-08      W36   My birthday!
   Y       2019-12-30       -    Not in the 2019 ISO week date year

Так что гнева не бывает. Программа или функция может выдавать ошибку или выводить что-то, не путаясь с номером недели ISO.

Пример 2 с N неуточненным.

Angry Type
Person?    Birthday   ISO Week   Comment
================================================================================
   N       2019-01-19      W03   
   Y       2019-02-04      W06   
   N       2019-02-05      W06   No anger because not an angry person
  ...             ...      ...   (No angry people until...)
   Y       2019-03-12      W11   Very Angry Person!
   N       2019-03-14      W11   
  ...             ...      ...   ... 

Вывод будет W11или что-то эквивалентное.

НГМ
источник
3
... Нет 29 февраля в 2019 году! Можете ли вы добавить работающий пример, пожалуйста?
Мохнатый
Каким должен быть результат, если никто не "очень зол"? Это может довольно легко случиться для маленькихN,
FryAmTheEggman
4
@ Shaggy, там могут быть люди, которые работают там, чей день рождения 29 февраля. Я говорю просто игнорировать эту возможность, так как это просто добавляет бессмысленный случай ИМО.
нгм
1
Если нет злых людей, подойдет любой подходящий вывод, который не W01-W52 или эквивалентный, или сообщение об ошибке. Я отредактирую вопрос, чтобы отразить это, когда я отключен от мобильного телефона.
НГМ
1
Может, это я, но у меня скорее общая вечеринка по случаю дня рождения, чем вообще никакой Разорвать всех тех, у кого есть свои дни рождения на выходных.
Кевин Круйссен

Ответы:

5

Python 2 , 172 202 байта

def f(n):
 D=set();A=[];R=randint
 while n:
	n-=1;w,d=R(1,52),R(1,5)
	if R(0,364)>104:D|={(w,d)};A+=[w]*(R(0,2)>1)
 return next((a for a in sorted(A)if[w for w,d in D].count(a)>1),0)
from random import*

Попробуйте онлайн!

упс! Пропустил требование; стоимость 30 байт.

ФП сообщает, что ваш день рождения не 29 февраля.

Если ваш день рождения 30 декабря, он не выпадет ни на одну неделю ISO 2019 года, поэтому в любом случае вы не можете быть недолгой неделей ISO 2019 года.

Осталось 364 дня рождения, чтобы считать вас очень злым. 104 из них выпадают по выходным, когда мы оговорили, что вы не будете очень сердиты по этому поводу. Таким образом, мы заботимся только о вас 260/365 времени; то есть когда R(0,364)>104( randintдиапазон включительно). Учитывая это ограничение, вполне вероятно, что ваш день рождения будет приходиться на любую из 52 недель ISO 2019 года и на любой день недели этой недели; и, независимо от того, что вы 1 из 3, вероятно, очень сердитый человек.

Тогда D - это набор, (weeknum,weekday)так что если потенциально сердитый человек разделяет фактический день рождения, тогда не нужно быть Амгри, если только на этой неделе у другого человека нет дня рождения.

0 возвращается, если в течение любой недели ISO 2019 не проявляются Очень Злые люди; в противном случае возвращается номер недели ISO самого раннего обвала.

Час Браун
источник
Разве вы не должны рассмотреть крайний случай 31 декабря 2019 года?
Чарли
1
@ Чарли: Конечно! Но 31 декабря 2018 года будет в той же неделе ISO 2019 года, что и 1 января 2019 года, таким образом, она станет частью этой «недели ревнивых вечеринок», так что все получится.
Час Браун
Я не эксперт по Python, но я полагаю, что ваш ответ не объясняет это: «но они не будут сердиться, если вечеринку расскажут люди, у которых день рождения одинаков». Вы все еще получили мой голос, хотя.
OOBalance
@OOBalance: Упс! Пропустил это; внесены изменения!
Час Браун
2

Желе ,  36 32  33 байта

+1 байт, чтобы исправить крайний случай 30-го декабря, которого я не заметил (как указал Час Браун в комментариях под ОП)

-4 благодаря Эрику Аутгольферу (встроенный помощник и использование внешнего продукта)

7R2<52×þFX)Ġị$,3XỊ¤€ṁ@\PṢ€Ḋ€Fḟ0Ḣ

Монадическая ссылка, которая дает целое число в [0,52] где 0 означает, что в течение года вообще не было очень злых людей, а другие результаты - номера недели ISO.

Попробуйте онлайн!

Или посмотрите эту версию, в которой напечатаны сгруппированные недели, в которые лежат дни рождения каждого человека (0 для выходных), затем напечатан упорядоченный список списков того, принадлежат ли эти люди типу «Очень сердитый», и, наконец, напечатает результат.

Джонатан Аллан
источник
1

Java 8, 198 байт

double r(){return Math.random();}

n->{int r=52,a[]=new int[r];for(;n-->0;)if(r()*364>104)++a[(int)(r()*r)];for(;++n<52;)r=r>51&a[n]>1&r()<1-5/Math.pow(5,a[n])&r()<1-Math.pow(2./3,a[n])?n:r;return r;}

Выход начинается с нуля (0-51); значение 52 указывает на отсутствие очень сердитых людей. Попробуйте это онлайн здесь .

Ungolfed:

double r() { return Math.random(); } // shortcut for Math.random(), saves a few bytes

n -> { // lambda taking an intger argument and returning an integer
    int r = 52, // this will hold the result; set to the value for "no Very Angry people" for now
    a[] = new int[r]; // array counting the people whose birthday lies in each week
    for(; n-- > 0; ) // for each person:
        if(r() * 364 > 104) // determine whether their birthday is on a weekday that is not the 30th of December ...
            ++a[(int) (r() * r)]; // ... only if so, increment the counter for a random ISO week
    for(; ++n < 52; ) // loop through the weeks; n is -1 before the loop
        r = r > 51   // if r is still the default ...
          & a[n] > 1 // ... and there is more than one person with a birthday that week ...
          & r() < 1 - 5/Math.pow(5, a[n]) // ... and at least two people have a different birthday ...
          &r() < 1 - Math.pow(2./3, a[n]) // ... and at least one person has the Very Angry personality type ...
          ? n  // ... set the current week as the result ...
          : r; // ... otherwise leave it the same
    return r;  // return the result
}
OOBalance
источник
Предлагаю 91>26вместо364>104
floorcat