jueves, 22 de diciembre de 2016

Simulación Numérica en Matlab para el modelo de Infiltración 1D

Realizaremos la simulación de Infiltración en un medio poroso y tomaremos como referencia a dos papers: el de Kumar y el de Celia de 1990.

Ecuación general de flujo no saturado

El flujo en zonas saturadas indica que cuando se alcanza una cierta zona(llamada zona saturada), la humedad es constante, así no habría nada que modelar en ese caso.

De acuerdo con la ley de Darcy, para una dimensión de flujo vertical, el volumen de flujo q(cm^3/cm^3/h) puede ser escrito como

$$q = -K \frac{\partial }{\partial z}(h-z) =-K (\frac{\partial h}{\partial z}-1)  $$
Donde K es la conductividad hiráulica(cm/h), "h" es la presión de agua en el suelo(relativo a la atmósfera) expresado en cm de agua y "z" es la componente vertical considerado positivo cuando va hacia abajo.

Del paper obtenemos las ecuaciones a usar:
$$ C = \frac{\mathrm{d} \theta}{\mathrm{d} h} $$
$$C(h) \frac{\partial h}{\partial t} = \frac{\partial }{\partial z} [K(h) (\frac{\partial h}{\partial z}-1)]$$
La funcion theta indica la humedad para una profundidad y tiempo dado.
Para el estudio, las condiciones iniciales son definidas como
$$\theta (z, t=0) = 0.1$$
$$\theta (z=0, t) = 0.267$$
La primera condición indica que el suelo va estar recibiendo una fuente de fluido constantemente, siempre en z=0(la superficie) se tendra una humedad de 0.267.
La segunda condición indica que inicialmente el suelo estaba casi seco en la zona no saturada.

Simulación

Luego del tiempo 0 empieza la simulación y del paper de Celia(referenciadas al principio) tenemos las siguientes relaciones:
$$K = K_s  \frac{A}{A+ \left | h^{\beta_1} \right |}$$
Donde Ks=34 cm/h, A=1175000, b1 =4.74 y
$$ \theta = \frac{\alpha (\theta_s \theta_r)}{\alpha+ \left | h^{\beta_2} \right |}+\theta_r$$
Donde theta_s =0.287, theta_r = 0.075, alfa = 1611000, b2 = 3.96.

Usando diferencias finitas

$$ C_i^{j+a} \frac{h_i^{j+1} -h_i^j}{\Delta t} = \frac{1}{\Delta z}\left [
 K_{i+1/2}^{j+a}\left (\frac{h_{i+1}^{j+a} -h_i^{j+a}}{\Delta z} -1\right )-
K_{i-1/2}^{j+a}\left ( \frac{h_{i}^{j+a} -h_{i-1}^{j+a}}{\Delta z} -1\right ) \right ]   $$

Donde "a" es un factor de peso entre 0 y 1, siendo a = 0 el esquema explicito, a = 0.5 el esquema de Crank - Nicolson y a = 1 el esquema implicito.

Ejemplo con 41 nodos de profundidad (0-40)

Si se desea el esquema explicito (a = 0), se puede emplear simplemente el siguiente código:

thetaS = 0.287; thetaR = 0.075; alfa = 1.611e6;
beta2 = 3.96;
tf = @(h) (alfa.*(thetaS-thetaR))./(alfa+(abs(h)).^beta2) + thetaR;
Ks = 0.00944; Ar = 1.175e6; beta1 = 4.74; %Ks debe estar en cm/s
kf = @(h) Ks.*Ar./(Ar+ abs(h).^beta1);
cf =@(h) -alfa*beta2*(thetaS-thetaR)*sign(h).*abs(h).^(beta2-1)./(alfa+abs(h).^beta2).^2;
hf =@(t) abs(alfa.*(thetaS-t)./(t-thetaR)).^(1/beta2);

z_max = 40;
n=40; T=360; dz=z_max/n; dt=0.4;
t=0.1*ones(1,n);
h = -hf(t);
h(1) = -hf(0.267);
h(n) = -hf(0.1);
k=kf(h);
c =cf(h);
temp = h;

for j=1:dt:T
    for i=2:n-1
        temp(i) = h(i)+dt/dz/c(i)*(sqrt(k(i)*k(i+1))*((h(i+1)-h(i))/dz -1)...
        - sqrt(k(i-1)*k(i))*((h(i)-h(i-1))/dz -1));
    end
    h = temp;
    k = kf(h);
    c = cf(h);
end
z=0:n-1;
plot(z,h,'k');

Los valores de c y de k se aproximan mediante:
$$ C_i^{j+a} = F_1 = (1-a)C_i^j + a C_i^{j+1}$$
$$ K_{i+1/2}^{j+a} = F_2 = (1-a)K_{i+1/2}^j + a K_{i+1/2}^{j+1}= (1-a)\sqrt{K_i^j K_{i+1}^j} +a\sqrt{K_i^{j+1} K_{i+1}^{j+1}}$$
$$ K_{i-1/2}^{j+a} = F_3 = (1-a)K_{i-1/2}^j + a K_{i-1/2}^{j+1}= (1-a)\sqrt{K_{i-1}^j K_{i}^j} +a\sqrt{K_{i-1}^{j+1} K_{i}^{j+1}}$$


Acomodando la ecuación para poder formar un sistema lineal
$$\left [ -aF_3 \frac{\Delta t}{(\Delta z)^2} \right ] h_{i-1}^{j+1}+
\left [ F_1+aF_2 \frac{\Delta t}{(\Delta z)^2}+aF_3 \frac{\Delta t}{(\Delta z)^2} \right ] h_{i}^{j+1}+
\left [ -aF_2 \frac{\Delta t}{(\Delta z)^2} \right ] h_{i+1}^{j+1}$$

$$ =
\left [ (1-a)F_3 \frac{\Delta t}{(\Delta z)^2} \right ] h_{i-1}^{j}+
\left [ F_1-(1-a)F_2 \frac{\Delta t}{(\Delta z)^2}-(1-a)F_3 \frac{\Delta t}{(\Delta z)^2} \right ] h_{i}^{j}+
\left [ (1-a)F_2 \frac{\Delta t}{(\Delta z)^2} \right ] h_{i+1}^{j}+
(F_3 - F_2)\frac{\Delta t}{\Delta z} $$

Tenemos que resolver el siguiente sistema lineal

$$\begin{bmatrix}
F_1^1+aF_2^1 \frac{\Delta t}{(\Delta z)^2}+aF_3^1 \frac{\Delta t}{(\Delta z)^2}  &  -aF_2^1 \frac{\Delta t}{(\Delta z)^2} & 0 & \cdots  & 0\\
 -aF_3^2 \frac{\Delta t}{(\Delta z)^2}& F_1^2+aF_2^2 \frac{\Delta t}{(\Delta z)^2}+aF_3^2 \frac{\Delta t}{(\Delta z)^2} & -aF_2^2 \frac{\Delta t}{(\Delta z)^2} & \cdots  & 0\\
 &  &  &  & \\
 \vdots & \ddots  & \ddots  & \ddots  & \vdots \\
 0& \cdots  & 0 & -aF_3^{39} \frac{\Delta t}{(\Delta z)^2} & F_1^{39}+aF_2^{39} \frac{\Delta t}{(\Delta z)^2}+aF_3^{39} \frac{\Delta t}{(\Delta z)^2}
\end{bmatrix}
\begin{bmatrix}
h_{1}^{j+1}\\
 h_{2}^{j+1}\\
h_{3}^{j+1}\\
\vdots \\
h_{39}^{j+1}
\end{bmatrix}$$

$$ = $$

$$\begin{bmatrix}
F_1^1-(1-a)F_2^1 \frac{\Delta t}{(\Delta z)^2}-(1-a)F_3^1 \frac{\Delta t}{(\Delta z)^2}  &(1-a)F_2^1 \frac{\Delta t}{(\Delta z)^2} & 0 & \cdots  & 0\\
 (1-a)F_3^2 \frac{\Delta t}{(\Delta z)^2}& F_1^2-(1-a)F_2^2 \frac{\Delta t}{(\Delta z)^2}-(1-a)F_3^2 \frac{\Delta t}{(\Delta z)^2} & (1-a)F_2^2 \frac{\Delta t}{(\Delta z)^2} & \cdots  & 0\\
 &  &  &  & \\
 \vdots & \ddots  & \ddots  & \ddots  & \vdots \\
 0& \cdots  & 0 & (1-a)F_3^{39} \frac{\Delta t}{(\Delta z)^2} & F_1^{39}-(1-a)F_2^{39} \frac{\Delta t}{(\Delta z)^2}-(1-a)F_3^{39} \frac{\Delta t}{(\Delta z)^2}
\end{bmatrix}
\begin{bmatrix}
h_{1}^{j}+(F_3^1 - F_2^1)\frac{\Delta t}{\Delta z}+aF_3^1 \frac{\Delta t}{(\Delta z)^2} h_0^{j+1} + (1-a)F_3^1 \frac{\Delta t}{(\Delta z)^2} h_0^{j} \\
 h_{2}^{j}\\
h_{3}^{j}\\
\vdots \\
h_{39}^{j}+(F_3^{39} - F_2^{39})\frac{\Delta t}{\Delta z}+aF_3^{39} \frac{\Delta t}{(\Delta z)^2} h_{40}^{j+1} + (1-a)F_3^{39} \frac{\Delta t}{(\Delta z)^2} h_{40}^{j}
\end{bmatrix}$$
Valido para j = 0,1, ... , M , M es un número natural tal que dt = T/M(puede ser igual o redondearse al mínimo entero).

El código general es el siguiente, agrupe los términos por comodidad en t1,t2,t3 y ti(término independiente).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
%   Solucón Numérica para la ecuacuón de Richards
%    Infiltración de líquido en medio poroso
%    
%
%
%
% Forma general
tic ();
thetaS = 0.287; thetaR = 0.075; alfa = 1.611e6;
beta2 = 3.96;
tf = @(h) (alfa.*(thetaS-thetaR))./(alfa+(abs(h)).^beta2) + thetaR;
Ks = 0.00944; Ar = 1.175e6; beta1 = 4.74; %Ks debe estar en cm/s
kf = @(h) Ks.*Ar./(Ar+ abs(h).^beta1);
cf =@(h) -alfa*beta2*(thetaS-thetaR)*sign(h).*abs(h).^(beta2-1)./(alfa+abs(h).^beta2).^2;

hf =@(t) abs(alfa.*(thetaS-t)./(t-thetaR)).^(1/beta2);
z_max = 40;
n=z_max; T=300; dz=z_max/n; dt=0.4;
a = 0.5; 
u=dt/dz^2;
t=0.1*ones(1,n);
h = -hf(t);
h(1) = -hf(0.267);
h(n) = -hf(0.1);
k=kf(h);
c =cf(h); 
hj1 = h;
cj1=c;
kj1 = k;
temp = h; 

for j=1:dt:360
    %PREDICTOR
    for i=2:n-1
        temp(i) = h(i)+dt/dz/c(i)*(sqrt(k(i)*k(i+1))*((h(i+1)-h(i))/dz -1)...
        - sqrt(k(i-1)*k(i))*((h(i)-h(i-1))/dz -1));
    end
    hj1 = temp;
    kj1 = kf(hj1);
    cj1 = cf(hj1);
   %CORRECTOR
    for i=2:n-1
        f1(i-1) = (1-a)*c(i)+a*cj1(i);
        f2(i-1) = (1-a)*sqrt(k(i)*k(i+1))+a*sqrt(kj1(i)*kj1(i+1));
        f3(i-1) = (1-a)*sqrt(k(i)*k(i-1))+a*sqrt(kj1(i)*kj1(i-1));
        t1(i-1) = -a*u*f3(i-1);
        t2(i-1) = f1(i-1)+a*u*f2(i-1)+a*u*f3(i-1);
        t3(i-1) = -a*u*f2(i-1);
        t1b(i-1) = (1-a)*u*f3(i-1);
        t2b(i-1) = f1(i-1)-(1-a)*u*f2(i-1)-(1-a)*u*f3(i-1);
        t3b(i-1) = (1-a)*u*f2(i-1);
        ti(i-1) = dt/dz*(f3(i-1)-f2(i-1));
    end
    ti(1) = ti(1) - t1(1)*h(1)+t1b(1)*h(1);
    ti(n-2) = ti(n-2) - t3(n-2)*h(n)+t3b(n-2)*h(n);
    B=diag(t1b(2:end),-1)+diag(t2b)+...
    diag(t3b(1:n-3),+1);
    A=diag(t1(2:end),-1)+diag(t2)+...
    diag(t3(1:n-3),+1);
    b = ti;
    x0 = h(2:n-1);
    h(2:n-1) = A\(B*x0'+b');
    k = kf(h);
    c = cf(h);
    temp = h;
end

z=0:n-1;
elapsed_time = toc ();
fprintf('se demoro %4.4f segundos \n',elapsed_time);
plot(z,h,'r');

Este ejemplo esta con el esquema de Crank Nickolson (a = 0.5), puedes modificar haciendo varia el "a", "dt", "T", "n", "dz", consultar las referencias para ver los valores de convergencia.

Muestra para T=360, T=720 y T= 0.8 horas = 8 x 360 s




Muestra de los esquemas para dt = 0.4, T=360, n=40 y valores de a entre 0 y 1.
Casi no se nota la diferencia.


Para dt = 3 , se ve cuando a< 0.5 diverge y cuando es mayor converge.

Continuaré en otro post, espero haberles ayudado ;)

domingo, 26 de julio de 2015

RNA - Aprender un numero digital

RNA - Aprender un numero digital

Con la plantilla utilizada para construir una red neuronal de la entrada anterior, la modificaremos  para el siguiente modelo:
Ahora la capa "K" tiene 4 nodos(neuronas) con 5 entradas más una entrada del Bias(entrada de otra neurona como parte de una red) , así tendría 6 entradas para cada nodo "K". Para la capa "J" tenemos 5 nodos con 7 entradas más una entrada como "bias" , lo que suma 8 entradas para cada nodo de la capa "J".

                   Numero        Representación digital          Representación Binaria
                      0                      1  1  1  0  1  1  1                        0  0  0  0  0
                      1                      1  0  0  0  0  0  1                        0  0  0  0  1
                      2                      1  1  0  1  1  1  0                        0  0  0  1  0
                      3                      1  1  0  1  0  1  1                        0  0  0  1  1
                      4                      1  0  1  1  0  0  1                        0  0  1  0  0
                      5                      0  1  1  1  0  1  1                        0  0  1  0  1
                      6                      0  1  1  1  1  1  1                        0  0  1  1  0
                      7                      1  1  0  0  0  0  1                        0  0  1  1  1
                      8                      1  1  1  1  1  1  1                        1  0  0  0  0
                      9                      1  1  1  1  0  1  1                        1  0  0  0  1

La representación digital serán la entradas junto a un balance del "bias"(en este caso -1) y la representación binaria es lo que la red debe aprender



public class TestNumero {                            //NK NJ EK EJ
    static RedNeuronal1 redNeuronal = new RedNeuronal1( 4, 5, 6, 8);
    static double balance = -1;                      
    static double[][] capaI = {{1,1,1,0,1,1,1,balance},  //0
                 {1,0,0,0,0,0,1,balance},  //1
                               {1,1,0,1,1,1,0,balance},  //2
                               {1,1,0,1,0,1,1,balance},  //3
       /*rep. digital*/        {1,0,1,1,0,0,1,balance},  //4
                               {0,1,1,1,0,1,1,balance},  //5
                               {0,1,1,1,1,1,1,balance},  //6
                               {1,1,0,0,0,0,1,balance},  //7
                               {1,1,1,1,1,1,1,balance},  //8
                               {1,1,1,1,0,1,1,balance}}; //9
    static double[][]  aprender =  {{0,0,0,0,0,0,0,0,1,1},
        {0,0,0,0,1,1,1,1,0,0},
                                    {0,0,1,1,0,0,1,1,0,0},
                                    {0,1,0,1,0,1,0,1,0,1}}; 
                                  //0  1 2 3 4 5 6 7 8 9    rep. binaria



Descargar archivo con frame para aprender un numero digital.
Descargar plantilla RNA
RNA - Aprender si un cuadrado es par

Definiremos los cuadrados impares, y definiremos a la cantidad impar con el valor de " 0 ".
Solo será par cuando dos casillas estén pintadas y tendrá el valor de " 1 ". No estarán definidas el cuadro sin pintar ni el cuadro con todas las casillas pintadas.


Cada nodo posee un vector de entradas(en este caso son 5 para la capa J y 3 para la capa K), y cada entrada tiene un peso("inicialmente aleatorios") y un función de activación(en este ejemplo sera la funcion sigmoidal).

También para cada nodo tendremos un error , utilizaremos el entrenamiento Backpropagation .






Construimos la clase nodo("neuron1")

package parimparrn;

public class Neuron1 {
    private double activacionu;
 double [] entradas;
 double [] pesos;
 double errorNodo;
 static Sigmoide sigmoide;
        public Neuron1(int nentradas)
 {
  pesos = new double[nentradas];
  entradas = new double[nentradas];
  sigmoide = new Sigmoide();
  errorNodo = 0;
 }
 public void activacion()
 {
  double suma = 0;
  for(int i=0;i<entradas.length;i++)
  {
   suma =suma + entradas[i]*pesos[i];
  }
  activacionu = sigmoide.funcion(suma);
 }

    public double[] getEntradas() {
        return entradas;
    }

    public void setEntradas(double[] entradas) {
        this.entradas = entradas;
    }

    public double[] getPesos() {
        return pesos;
    }

    public void setPesos(double[] pesos) {
        this.pesos = pesos;
    }
 public void verEntradas()
 {
  System.out.print(" entradas  ");
  for(int i=0;i<entradas.length;i++)
  {
   System.out.println(entradas[i]);
  }
 }
 public void verPesos()
 {
  System.out.println(" *** pesos ** ");
  for(int i=0;i<pesos.length;i++)
  {
   System.out.println(""+pesos[i]);
  }
 }
 public double getActivacion()
 {
  return activacionu;
 }
 public void verActivacion()
 {
  System.out.println("activacion");
  System.out.println(""+activacionu);
 }
 public double getError()
 {
  return errorNodo;
 }
 public void setError(double error)
 {
  errorNodo=error;
 }
        
}
Adjunto el proyecto , el archivo con frame , utiliza los pesos aprendidos tras ejecutar el método run de la clase TestRN.En  el proyecto sin frame se ejecuta el método y se encuentra los pesos para la red.
Descargar Proyecto completo con frame
Descargar Proyecto completo sin frame
Descargar  plantillas de RNA

jueves, 2 de julio de 2015

Ecuación de Lorenz


El siguiente sistema , modela el comportamiento de una atmósfera simple.
Para rho<24.75 el sistema es estable,pero para rho>24.75 es impredecible analíticamente.
File en lenguaje Matlab.

1
2
3
4
5
6
7
8
function dx=lorenzatt(T,X)
 rho = 28; sigma = 10;  beta = 8/3;
 dx = zeros(3,1);
 dx(1) = sigma*(X(2) - X(1));
 dx(2) = X(1)*(rho - X(3))-X(2);
 dx(3) = X(1)*X(2) - beta*X(3);
 return
end

Listas palindromas

20.11 Escriba un programa que utilice un objeto pila para determinar si una cadena es una palíndroma (es decir, que la cadena se deletree en forma idéntica, tanto al revés como al derecho). El programa debe ignorar espacios y puntuación.

#include <iostream>
using namespace std;
struct nodo
{
 char dato;
 struct nodo *sig;
};

void inicializar(nodo **cab)
{
 *cab = NULL;
}

void push(nodo **cab , char nuv)
{
 nodo *q;
 q = new nodo;
 q->dato = nuv;
 if(*cab == NULL)
 {
  q->sig = *cab;
  *cab = q;
 }
 else
 {
  q->sig = *cab;
  *cab = q;
 }
}

char pop(nodo **cab)
{
 nodo *aux;
 char num;
 aux = *cab;
 if(aux)
 {
  num = aux->dato;
  *cab = (*cab)->sig;
  delete aux;
  return num;
 }
 else
 {
  return 0;
 }
}

int comparar(nodo *cab, nodo *cab2 , int n)
{
     int b = 1; 
     for(int i=0;i<n;i++)
     {
         if(cab->dato == cab2->dato)
         {
             cab = cab->sig;
             cab2 = cab2->sig;
         }
         else
             b = 0;
     }
     return b;
}

void mostrar(nodo *cab)
{
 while(cab)
 {
  cout<<cab->dato;
  cab = cab->sig;
 }
 cout<<"\n\n\n";
}

int main()
{
 nodo *cab , *cab2;
 inicializar(&cab);
 inicializar(&cab2);
    string palabra ="anita lava la.. tina";
 //cout<<" ingresa palabra:  ";
 //cin>>palabra;
 int cont=0;
 for(int i=(palabra.length()-1);i>=0;i--)
 {
            if(palabra[i] != ' ')
            {     if(palabra[i] != '.')
                    push(&cab , palabra[i]);
                  else
                      cont++;  }
            else
                cont++;
    }
    for(int i=0;i<palabra.length();i++)
 {
            if(palabra[i] != ' ')
            {     if(palabra[i] != '.')
                    push(&cab2 , palabra[i]);
                  else
                      cont++;  }
            else
                cont++;
    }
 cout<<comparar(cab , cab2, palabra.length()-cont)<<" '1 iguales , 0 diferentes'  \n";
    mostrar(cab2);
 mostrar(cab);
 
 system("pause");
 return 0;
}


Invertir lista de caracteres

20.9 Escriba un programa para crear un objeto lista enlazada de 10 caracteres, y que luego cree un segundo objeto lista que contenga una copia de la primera lista, pero en orden inverso.

#include <iostream>
using namespace std;

struct nodo
{
       char info;
       struct nodo *sig;
};

void generarLista(nodo **inicio)
{
     nodo *q , *fin;
     for(int i=0;i<5;i++)
     {
             q = new nodo;
             q->info = (char)(rand()%10+70);
             
             if(*inicio == NULL)
             {
                  q->sig = *inicio;
                  *inicio = q;
                  fin = q;
             }
             else
             {
                 q->sig = fin->sig;
                 fin->sig = q;
                 fin = q;
             }
     }
}
nodo *obtenerFin( nodo *inicio)
{
     while( inicio->sig != NULL )
         inicio=inicio->sig;
     
     return inicio;
}


nodo *EliminarFin( nodo *inicio )
{
     nodo *fin , *aux;
     fin = obtenerFin(inicio);
     aux=inicio;
     
     while( aux->sig != fin )
         aux=aux->sig;
     
     aux->sig= fin->sig;
     
     
     delete fin;
     
     return inicio;
}  

nodo *InsertarFinal( nodo *inicio ,nodo *fin, char nom)
{
     nodo *q ;
     q = new nodo;
     q->info = nom;
     
     
     if(fin==NULL)
     {
         q->sig = inicio;
         inicio  = q;
         fin     = q;        
     }
     else
     {
         q->sig   = fin->sig;
         fin->sig = q;
         fin       = q;
     }
     return inicio;
}    

void mostrar(nodo *inicio)
{
     while(inicio)
     {
          cout<<inicio->info<<"  ";
          inicio = inicio->sig;
     }
     cout<<"\n\n\n";
}

int main()
{
    nodo *inicio , *inicio2 , *fin2;
    inicio  = NULL;
    inicio2 = NULL;
    fin2 = NULL;
    generarLista(&inicio);
    mostrar(inicio);
    
    inicio2 = InsertarFinal(inicio2 ,fin2 , obtenerFin(inicio)->info);
    inicio  = EliminarFin(inicio);
    inicio2 = InsertarFinal(inicio2 ,obtenerFin(inicio2) , obtenerFin(inicio)->info);
    inicio  = EliminarFin(inicio);
    inicio2 = InsertarFinal(inicio2 ,obtenerFin(inicio2) , obtenerFin(inicio)->info);
    inicio  = EliminarFin(inicio);
    inicio2 = InsertarFinal(inicio2 ,obtenerFin(inicio2) , obtenerFin(inicio)->info);
    inicio  = EliminarFin(inicio);
    inicio2 = InsertarFinal(inicio2 ,obtenerFin(inicio2) , obtenerFin(inicio)->info);
    
    mostrar(inicio2);
    
    system("pause");
    return 0;
}


Suma y promedio de una lista

20.8 Escriba un programa para insertar 25 enteros aleatorios de 0 a 100 en orden, en un objeto lista enlazada. El programa deberá calcular la suma de los elementos y el promedio de punto f lotante de los elementos.
 

/*
* C++ Suma y promedio de una lista simple
*
*/
 
#include <iostream>
#include <cstdlib>
 
using namespace std;
 
struct nodo{
       int nro;        // en este caso es un numero entero
       struct nodo *sgte;
};
 
typedef struct nodo *Tlista,*Tlista2;
 
Tlista inicio, fin;
Tlista2 inicio2,fin2;
 
void generarLista( Tlista &inicio, Tlista &fin, int n ) 
{
     Tlista q, t;
     Tlista r, s;
     
     for(int i=0; i<n; i++)
     {
         q = new(struct nodo);
         q->nro = rand()%100;
         
         r = new(struct nodo);
         r->nro = q->nro;
         
         if(inicio==NULL)
         {
              q->sgte = inicio;
              inicio  = q;
              fin     = q; 
         }
         else
         {
              q->sgte   = fin->sgte;
              fin->sgte = q;
              fin       = q;
         }
     }
     
     cout<<"\n\n\tLista de numeros generados... "<<endl;
}
  
 
void reportarLista(Tlista inicio)
{
     
     while(inicio != NULL)
     {
          cout << inicio->nro<<"  " ;
          inicio = inicio->sgte;
     }
 
}
 
void ordenarLista(Tlista lista)
{
     Tlista actual , siguiente;
     int t;
     
     actual = lista;
     while(actual->sgte != NULL)
     {
          siguiente = actual->sgte;
          
          while(siguiente!=NULL)
          {
               if(actual->nro > siguiente->nro)
               {
                    t = siguiente->nro;
                    siguiente->nro = actual->nro;
                    actual->nro = t;          
               }
               siguiente = siguiente->sgte;                    
          }    
          actual = actual->sgte;
          siguiente = actual->sgte;
           
     }
}
 
int suma( Tlista inicio )
{
    int suma = 0;
    while( inicio )
    {
        suma = suma + inicio->nro;
        inicio = inicio->sgte;
    }
    return suma;
}

/*                        Funcion Principal
------------------------------------------------------------------*/
 
int main()
{
    inicio = NULL;
    fin    = NULL;
    float sumar;
 
    system("color 0b");
    
    generarLista( inicio, fin, 25 );
    ordenarLista( inicio );
    cout<<"\n\n LISTA:\n\n";
    reportarLista( inicio );  
    sumar = suma( inicio ); 
    cout<<"\n\nsuma= "<<sumar<<"  promedio= "<<sumar/25<<"\n\n\n";      
    
 
   system("pause");
   
   return 0;
}