Existem duas categorias de soluções para esse tipo de problema: loterias tendenciosas e seqüências aleatórias filtradas / geradas .
Primeiro, vamos dispensar soluções fáceis, mas erradas, que não mantêm nenhum estado. Qualquer solução no estilo de loteria que não mantenha nenhum estado terá o número de vitórias em uma distribuição binomial, que falha no critério "quantas vezes". Você pode selecionar uma sequência aleatória que escolha todas as pessoas da mesma forma (basta dar uma olhada na lista; as permutações fornecem aleatoriedade), mas quando as pessoas começam a sair de férias, sua sequência agora tem falhas. A menos que você acompanhe, você se encontrará novamente com distribuições binomiais em vez de manter o mesmo esforço.
Vamos também nos comprometer a ter aleatoriedade real. Você pode querer isso para que, por exemplo, uma pessoa não possa agendar suas férias com base em um algoritmo determinístico, para que nunca esteja presente quando for a sua vez de comprar croissants (até que eles usem todos os dias de férias, suponho). .
Então, vamos aos dois tipos de soluções.
Para construir uma loteria tendenciosa, observe primeiro que podemos escolher praticamente qualquer distribuição contínua (com desvio finito) para gerar números para nossa loteria. O perdedor pode então ser a pessoa com o menor número. O viés mais simples é acompanhar se cada indivíduo comprou mais ou menos do que sua parte. Você pode medir o viés em unidades de croissants. Você pode ajustar o grau de aleatoriedade alterando a largura e o formato da distribuição - isso também determinará a que distância um indivíduo pode chegar "do mesmo número de vezes". Gaussianos são fáceis; eles permitem uma surpresa razoável sem ter caudas muito longas ("injustas"). Portanto, o formato básico da solução é (no código Scala)
case class Employee(var bias: Double) {
def eat { bias -= 1 }
def buy(n: Int) { bias += n }
def roll = bias + stdev * Random.nextGaussian
}
Você pode acompanhar quem comprou por último e dar a eles um grande bônus de viés (por exemplo 10*stdev
) para impedir que as pessoas comprem duas vezes seguidas, exceto no caso em que a estrutura de férias permitiu que todos comprassem a "última" vez. (ou seja, você compra e depois sai de férias.) A mesma coisa por não estar presente no dia em que foram selecionados. (Se alguém está ausente todos os outros dias eles eventualmente vão vir para cima como eles queimam através de seu bônus de viés;. Eu considero este um recurso e não um bug)
Então, você coleciona sua lista de funcionários atuais para o dia, faz com que todos rolem para a loteria, escolham a mais baixa e atualizam. Você pode escolher se o bônus de compra é igual ao número de funcionários (bom quando o custo é insignificante, mas a viagem para obter croissants é onerosa), o número de funcionários presentes (bom se a viagem é fácil, mas o custo é oneroso) ) ou algo no meio (para reconhecer os dois encargos). Provavelmente, é melhor ter apenas a penalidade de "comer" para as pessoas presentes, mas você pode fazê-lo de qualquer maneira, se achar que apenas estar de férias não lhe dá o tom certo em menos.
Para construir uma sequência aleatória filtrada, primeiro você precisa gerar uma sequência aleatória. Baralhar uma lista dos funcionários é a melhor maneira de começar. Basta percorrer a lista, em ordem, dia após dia. Se alguém não puder comprar porque está ausente ou não pode ser avisado ou comprado antes, pule-o. Agora você tem um problema: você está acumulando pessoas que foram ignoradas. Tudo bem, no entanto. Quando você chegar ao final da sua sequência, anexe a lista de funcionários ignorados à lista completa antes de embaralhar. Agora, a probabilidade de ocorrência é proporcional ao número de vezes que você foi ignorado, o que mantém a propriedade "mesmo número de vezes".
registro2( N)NN!NNregistro2[ ( N!NN)1 / N] ≈- 1registro( 2 )+ log22 π/ N√N≈ - 1,4NN= 10 1,14
Pessoalmente, sou a favor da solução tendenciosa da loteria, pois o controle sobre a aleatoriedade é melhor. Com sequências filtradas, você pode criar maneiras mais complexas de gerar sequências. Por exemplo, em vez de fazer uma permutação aleatória, faça trocas locais a uma certa distância ou permita a troca total de pessoas da piscina (mas elas vão para a lista ignorada) - mas essas coisas exigem mais esforço algorítmico. Com a loteria, você apenas ajusta o desvio padrão.