Introducción
En este desafío, su tarea es implementar una colección de funciones simples que juntas formen una mini biblioteca utilizable para distribuciones de probabilidad simples. Para acomodar algunos de los lenguajes más esotéricos que a la gente le gusta usar aquí, las siguientes implementaciones son aceptables:
- Un fragmento de código que define una colección de funciones con nombre (o equivalentes más cercanos).
- Una colección de expresiones que evalúan funciones nombradas o anónimas (o equivalentes más cercanos).
- Una sola expresión que evalúa varias funciones con nombre o anónimas (o equivalentes más cercanos).
- Una colección de programas independientes que toman entradas de la línea de comando, STDIN o equivalente más cercano, y salen a STDOUT o equivalente más cercano.
Las funciones
Deberá implementar las siguientes funciones, utilizando nombres más cortos si lo desea.
uniform
toma como entrada dos números de punto flotantea
yb
, y devuelve la distribución uniforme sobre[a,b]
. Puedes asumir esoa < b
; El casoa ≥ b
no está definido.blend
toma como entradas tres distribuciones de probabilidadP
,Q
yR
. Devuelve una distribución de probabilidadS
, que extrae valoresx
,y
yz
deP
,Q
yR
, respectivamente, y producey
ifx ≥ 0
, yz
ifx < 0
.over
toma como entrada un número de coma flotantef
y una distribución de probabilidadP
, y devuelve la probabilidad que sex ≥ f
mantiene para un número aleatoriox
extraído deP
.
Como referencia, over
se puede definir de la siguiente manera (en 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)
Puede suponer que todas las distribuciones de probabilidad dadas over
se construyen usando uniform
y blend
, y que lo único que un usuario va a hacer con una distribución de probabilidad es alimentarlo blend
o over
. Puede usar cualquier tipo de datos conveniente para representar las distribuciones: listas de números, cadenas, objetos personalizados, etc. Lo único importante es que la API funciona correctamente. Además, su implementación debe ser determinista, en el sentido de que siempre devuelve la misma salida para las mismas entradas.
Casos de prueba
Sus valores de salida deben ser correctos al menos a dos dígitos después del punto decimal en estos casos de prueba.
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