Introdução
Nesse desafio, sua tarefa é implementar uma coleção de funções simples que, juntas, formam uma mini-biblioteca utilizável para distribuições simples de probabilidade. Para acomodar algumas das línguas mais esotéricas que as pessoas gostam de usar aqui, as seguintes implementações são aceitáveis:
- Um trecho de código que define uma coleção de funções nomeadas (ou equivalentes mais próximos).
- Uma coleção de expressões que avaliam funções nomeadas ou anônimas (ou equivalentes mais próximos).
- Uma única expressão que avalia várias funções nomeadas ou anônimas (ou equivalentes mais próximos).
- Uma coleção de programas independentes que recebem entradas da linha de comando, STDIN ou equivalente mais próximo e são enviadas para STDOUT ou equivalente mais próximo.
As funções
Você deve implementar as seguintes funções, usando nomes mais curtos, se desejar.
uniform
toma como entrada dois números de ponto flutuantea
eb
, e retorna a distribuição uniforme no[a,b]
. Você pode assumir issoa < b
; o casoa ≥ b
é indefinido.blend
toma como entradas três distribuições de probabilidadeP
,Q
eR
. Retorna uma distribuição de probabilidadeS
, que desenha valoresx
,y
ez
deP
,Q
eR
, respectivamente, e produzy
sex ≥ 0
ez
sex < 0
.over
toma como entrada um número de ponto flutuantef
e uma distribuição de probabilidadeP
e retorna a probabilidade quex ≥ f
vale para um número aleatóriox
retiradoP
.
Para referência, over
pode ser definido da seguinte forma (em pseudocódigo):
over(f, uniform(a, b)):
if f <= a: return 1.0
else if f >= b: return 0.0
else: return (b - f)/(b - a)
over(f, blend(P, Q, R)):
p = over(0.0, P)
return p*over(f, Q) + (1-p)*over(f, R)
Você pode assumir que todas as distribuições de probabilidade atribuídas over
são construídas usando uniform
e blend
, e que a única coisa que um usuário fará com uma distribuição de probabilidade é alimentá-lo com blend
ou over
. Você pode usar qualquer tipo de dados conveniente para representar as distribuições: listas de números, seqüências de caracteres, objetos personalizados etc. A única coisa importante é que a API funcione corretamente. Além disso, sua implementação deve ser determinística, no sentido de sempre retornar a mesma saída para as mesmas entradas.
Casos de teste
Seus valores de saída devem estar corretos para pelo menos dois dígitos após o ponto decimal nesses casos de teste.
over(4.356, uniform(-4.873, 2.441)) -> 0.0
over(2.226, uniform(-1.922, 2.664)) -> 0.09550806803314438
over(-4.353, uniform(-7.929, -0.823)) -> 0.49676329862088375
over(-2.491, uniform(-0.340, 6.453)) -> 1.0
over(0.738, blend(uniform(-5.233, 3.384), uniform(2.767, 8.329), uniform(-2.769, 6.497))) -> 0.7701533851999125
over(-3.577, blend(uniform(-3.159, 0.070), blend(blend(uniform(-4.996, 4.851), uniform(-7.516, 1.455), uniform(-0.931, 7.292)), blend(uniform(-5.437, -0.738), uniform(-8.272, -2.316), uniform(-3.225, 1.201)), uniform(3.097, 6.792)), uniform(-8.215, 0.817))) -> 0.4976245638164541
over(3.243, blend(blend(uniform(-4.909, 2.003), uniform(-4.158, 4.622), blend(uniform(0.572, 5.874), uniform(-0.573, 4.716), blend(uniform(-5.279, 3.702), uniform(-6.564, 1.373), uniform(-6.585, 2.802)))), uniform(-3.148, 2.015), blend(uniform(-6.235, -5.629), uniform(-4.647, -1.056), uniform(-0.384, 2.050)))) -> 0.0
over(-3.020, blend(blend(uniform(-0.080, 6.148), blend(uniform(1.691, 6.439), uniform(-7.086, 2.158), uniform(3.423, 6.773)), uniform(-1.780, 2.381)), blend(uniform(-1.754, 1.943), uniform(-0.046, 6.327), blend(uniform(-6.667, 2.543), uniform(0.656, 7.903), blend(uniform(-8.673, 3.639), uniform(-7.606, 1.435), uniform(-5.138, -2.409)))), uniform(-8.008, -0.317))) -> 0.4487803553043079