## Importations

import random as rd
import numpy as np

## Loi certaine

def certaine(a) :
    return a

## Loi uniforme sur [[a,b]]

def uniforme(a,b) :
    return rd.randint(a,b)

## Loi de Bernoulli

def Bernoulli(p) :
    return int(rd.random() < p)

## Loi binomiale

def binomiale(n,p) :
    L = [Bernoulli(p) for _ in range(n)]
    return sum(L)

## Loi géométrique

def geometrique(p) :
    rang = 1
    while rd.random() > p :
        rang += 1
    return rang

## Loi de Poisson

def Poisson(mu) :
    k = 0
    r = rd.random()
    pk = np.exp(-mu)
    S = pk
    while S < r :
        k += 1
        pk *= mu/k
        S += pk
    return k

## Estimation d'espérance

def esperance(X,N) :
    S = 0
    for _ in range(N) :
        S += X()
    return S/N

## Estimation de variance

def variance(X,N) :
    m = esperance(X,N)
    def Y() :
        return (X()-m)**2
    return esperance(Y,N)

## Tests

a = 1
b = 6
p = 0.3
n = 10
mu = 4

def cert() :
    return certaine(a)
def unif() :
    return uniforme(a,b)
def Bern() :
    return Bernoulli(p)
def binom() :
    return binomiale(n,p)
def geom() :
    return geometrique(p)
def Poiss() :
    return Poisson(mu)

N = 1000
print("Espérances des lois usuelles :")
print("Loi certaine de valeur ",a," :")
print(esperance(cert,N))
print("Loi uniforme sur [",a,",",b,"] :")
print(esperance(unif,N))
print("Loi de Bernoulli de paramètre ",p," :")
print(esperance(Bern,N))
print("Loi binomiale de paramètres ",n,",",p," :")
print(esperance(binom,N))
print("Loi géométrique de paramètre ",p," :")
print(esperance(geom,N))
print("Loi de Poisson de paramètre ",mu," :")
print(esperance(Poiss,N))

print("\n")
print("Variances des lois usuelles :")
print("Loi certaine de valeur ",a," :")
print(variance(cert,N))
print("Loi uniforme sur [",a,",",b,"] :")
print(variance(unif,N))
print("Loi de Bernoulli de paramètre ",p," :")
print(variance(Bern,N))
print("Loi binomiale de paramètres ",n,",",p," :")
print(variance(binom,N))
print("Loi géométrique de paramètre ",p," :")
print(variance(geom,N))
print("Loi de Poisson de paramètre ",mu," :")
print(variance(Poiss,N))

## Loi quelconque sans espérance

def f(k) :
    return 1/(k*(k+1))

def simuleX() :
    S,k,r = f(1),1,rd.random()
    while S < r :
        k += 1
        S += f(k)
    return k