Festa de aniversário compartilhada

9

Um escritório (vamos chamá-lo de "O Escritório") reduzirá o tempo perdido em 2019, consolidando as festas de aniversário do escritório. Quaisquer duas pessoas com um aniversário entre segunda e sexta-feira (inclusive) da mesma semana serão comemoradas com uma festa de aniversário compartilhada em algum momento da semana. As pessoas cujos aniversários acontecem no sábado ou no domingo não recebem nenhuma festa.

Algumas pessoas não gostam de compartilhar uma festa de aniversário com pessoas que não compartilham seu aniversário real. Eles ficarão com muita raiva de ter uma festa de aniversário compartilhada .

Vamos simular um escritório e encontrar a primeira semana em que alguém fica muito irritada sobre sua festa de aniversário do Shared .

O desafio

Escreva um programa ou função que produza o primeiro número da semana ISO de 2019 em que alguém em um escritório simulado fica muito irritado com a festa de aniversário compartilhada , sujeito às seguintes regras básicas:

  • insira um número inteiro N > 1, que é o número de trabalhadores no escritório.
  • os N aniversários em si são distribuídos uniformemente aleatoriamente de 1º de janeiro a 31 de dezembro (ignore 29 de fevereiro).
  • mas as semanas úteis para determinar as Festas de Aniversário Compartilhadas são as Datas da Semana ISO de 2019, que são entre 2019-W01-1 (2018-12-31) e 2019-W52-7 (2019-12-29). Uma nova semana ISO começa toda segunda-feira. (Acho que isso é tudo o que você realmente precisa saber sobre as semanas da ISO para esse desafio).
  • para as pessoas N no escritório, cada uma tem uma chance de 1/3 de ter um tipo de personalidade de festa de aniversário compartilhada com muita raiva , então você terá que simular isso também.
  • mas eles não ficarão zangados se a festa for compartilhada com pessoas que têm o mesmo aniversário.
  • gerar o número da semana ISO (o formato exato para isso é flexível, desde que o número da semana esteja claro) para a primeira ocorrência de uma pessoa com muita raiva . Se não houver pessoas zangadas, você pode produzir qualquer coisa que não seja confundida com uma semana ISO ou o programa poderá errar, etc.

Algumas suposições simplificadoras:

  • como mencionei, ignore completamente a edição de 29 de fevereiro (uma complicação desnecessária)
  • ignore os feriados públicos (esta é uma comunidade internacional, portanto nossas férias serão diferentes) e apenas presuma que o escritório esteja aberto todos os dias da semana.

Regras

Isso é código-golfe. A resposta mais curta em bytes para cada idioma vence. Brechas padrão proibidas.

Boas explicações sobre o código.

Exemplos Trabalhados

Exemplo artificial 1 com entrada N = 7. A primeira e a segunda colunas são aleatórias, conforme descrito nas regras (mas não são realmente aleatórias aqui, é claro).

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

Portanto, nenhuma raiva acontece. O programa ou função pode gerar um erro ou gerar algo que não seja confundido com um número da semana ISO.

Exemplo 2 com N não especificado.

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   
  ...             ...      ...   ... 

A saída seria W11ou algo equivalente.

ngm
fonte
3
... Não há 29 de fevereiro de 2019! Você pode adicionar um exemplo, por favor?
Salsicha
Qual deve ser o resultado se ninguém estiver "muito zangado"? Isso poderia facilmente acontecer para pequeno . N
FryAmTheEggman
4
@ Shaggy, pode haver pessoas que trabalham lá, cujo aniversário é 29 de fevereiro. Estou dizendo para simplesmente ignorar essa possibilidade, uma vez que apenas adiciona um caso de IMO sem sentido.
Ng
11
Se não houver pessoas com raiva, qualquer saída adequada que não seja de W01 a W52 ou equivalente, ou uma mensagem de erro, está correta. Vou editar a pergunta para refletir isso quando estiver fora do celular.
ngm
11
Talvez seja eu, mas prefiro ter uma festa de aniversário compartilhada do que nenhuma. Rasgue todos aqueles que fazem aniversário no fim de semana.
Kevin Cruijssen 26/07

Respostas:

5

Python 2 , 172 202 bytes

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*

Experimente online!

oops! Perdeu um requisito; custa 30 bytes.

O OP informa que seu aniversário não é 29 de fevereiro.

Se seu aniversário for 30 de dezembro, ele não cairá em nenhuma semana ISO de 2019, portanto, em qualquer caso, você não poderá ser uma semana ISO muito irritada de 2019.

Isso deixa 364 outros aniversários para considerar que você está com muita raiva. 104 deles caem nos fins de semana, quando estipulamos que você não ficará muito zangado com isso. Então, nós só nos preocupamos com você 260/365 do tempo; ou seja, quando R(0,364)>104( randinto intervalo é inclusivo). Dada essa restrição, é equivalente que o aniversário de seu dia da semana caia em qualquer uma das 52 semanas ISO de 2019 e em qualquer dia da semana dessa semana; e, independentemente, é provável que você seja 1 em cada 3 uma pessoa com muita raiva.

D é então um conjunto de (weeknum,weekday)modo que, se uma pessoa potencialmente zangada compartilha um aniversário real, não há necessidade de ficar com fome, a menos que haja outra pessoa fazendo aniversário nessa semana.

0 é retornado se nenhuma pessoa com muita raiva se manifestar durante qualquer semana da ISO 2019; caso contrário, o número da semana ISO do primeiro colapso será retornado.

Chas Brown
fonte
Você também não deveria considerar o caso extremo de 31 de dezembro de 2019?
2626 Charlie
11
@Charlie: Claro! Mas 31 de dezembro de 2018 está na mesma semana ISO de 2019 que 1º de janeiro de 2019, portanto, faria parte dessa "semana de festa ciumenta", então funciona.
Chas Brown
Não sou especialista em Python, mas acredito que sua resposta não explica isso: "mas eles não ficarão zangados se a festa for compartilhada com pessoas que têm o mesmo aniversário". Você ainda recebeu meu voto positivo.
OOBalance
@OOBalance: Opa! Perdeu isso; alterados!
Chas Brown
2

Geléia ,  36 32  33 bytes

+1 byte para corrigir o caso extremo de 30 de dezembro que eu não havia notado (conforme destacado por Chas Brown nos comentários abaixo do OP)

-4 graças a Erik the Outgolfer (ajudante em linha e uso do produto externo)

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

Um link monádico que gera um número inteiro em onde significa que não há pessoas com muita raiva durante o ano e outras saídas são números ISO da semana.0[0,52]0

Experimente online!

Ou veja esta versão que imprime as semanas em que o aniversário de cada pessoa está (0 nos fins de semana) agrupadas, depois imprime uma lista com as mesmas ordens de se essas pessoas são do tipo Muito Irritado e, finalmente, imprime o resultado.

Jonathan Allan
fonte
1

Java 8, 198 bytes

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;}

A saída é baseada em zero (0-51); um valor de 52 indica que não há pessoas muito zangadas . Experimente online aqui .

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
fonte
Sugerir em 91>26vez de364>104
ceilingcat 20/09/19