function [distrib, valores] = distrib_una_va(xpart,xval)
%  [distrib, valores] = distrib_una_va(xpart,xval)
%  Dada una variable aleatoria en forma particional, hallar su distribucion
%  La variable esta definida sobre el espacio muestral [0,1],
%     con una distribucion uniforme
%  xpart: vector (fila o columna) de puntos que definen la particion
%         1er elemento: 0, ultimo elemento: 1, orden ascendiente
%  xval:  valores correspondientes a los distintos elementos de la particion
%  valores: valores _distintos_ que toma la variable aleatoria xval
%  distrib: probabilidad asociada a cada uno de los valores anteriores
% 
%  Ejemplo:  xpart = [ 0 1/4 1/3 1/2 3/4 1 ]
%            xval =  [  10  15  20  15  10 ]
%  donde, eg, xval = 20 en el subintervalo (1/3,1/2) (los extremos no importan)
%  Notar, en particular, que length(xval) = length(xpart) - 1
%  puesto que length(xval) es el numero de elementos de la particion,
%  que es el numero de puntos que la definen menos uno (son los intervalos
%  entre puntos consecutivos)
%  El output es: distrib = [ 1/2 1/3 1/6 ], valores = [ 10 15 20 ]

%% Funcion de Matlab/Octave -- Ricard Torres, 2015 (sin acentos)

% En primer lugar, comprobamos que los argumentos sean correctos
if ( nargin ~= 2 )
   mostrar_uso() ;
   error('La funcion debe tener dos argumentos') ;
end

if ~ and( isvector(xpart), isvector(xval) )
   mostrar_uso() ;
   error('Los argumentos de la funcion deben de ser vectores') ;
end

lp = length(xpart); lv = length(xval);

if ~ ( lv == lp - 1 )
   mostrar_uso() ;
   error('Debe de haber un valor para cada elemento de la particion') ;
end

if ~ and( (xpart(1) == 0), (xpart(end) == 1) )
   mostrar_uso() ;
   error('La particion debe empezar con 0 y acabar con 1') ;
end

is_ascending = true;
for i = 2 : lp
    if xpart(i) <= xpart(i-1), is_ascending = false; end
end

if ~ is_ascending
   mostrar_uso() ;
   error('El vector que define la particion debe tener orden ascendiente') ;
end

% Ahora desarrollamos los calculos propiamente dichos
valores = unique(sort(xval));
distrib = zeros(1,length(valores));
for i = 1 : length(valores)
    for j = 1 : length(xval)
        if ( valores(i) == xval(j) )
           distrib(i) = distrib(i) + xpart(j+1) - xpart(j) ;
        end
    end
end

end

% Mensaje de ayuda en caso de error
function mostrar_uso()
fprintf('Uso: [distrib, valores] = distrib_una_va(xpart,xval)\n');
fprintf('Dada una variable aleatoria en forma particional, ');
fprintf('hallar su distribucion\n');
fprintf('La variable esta definida sobre el espacio muestral [0,1],\n');
fprintf('  con una distribucion uniforme\n');
fprintf('xpart: vector (fila o columna) de puntos que definen la particion\n');
fprintf('    1er elemento: 0, ultimo elemento: 1, orden ascendiente\n');
fprintf('xval:  valores correspondientes a los distintos elementos ');
fprintf(' de la particion\n');
fprintf('valores: valores _distintos_ que toma la variable aleatoria xval\n');
fprintf('distrib: probabilidad asociada a cada uno de los valores anteriores\n');
fprintf('\nEjemplo:  xpart = [ 0 1/4 1/3 1/2 3/4 1 ]\n');
fprintf('          xval =  [  10  15  20  15  10 ]\n');
fprintf('donde, eg, xval = 20 en el subintervalo (1/3,1/2) ');
fprintf(' (los extremos no importan)\n');
fprintf('Notar, en particular, que length(xval) = length(xpart) - 1\n');
fprintf('puesto que length(xval) es el numero de elementos de la particion,\n');
fprintf('que es el numero de puntos que la definen menos uno\n');
fprintf(' (son los intervalos entre puntos consecutivos)\n');
fprintf('El output es: distrib = [ 1/2 1/3 1/6 ], valores = [ 10 15 20 ]\n');
end

