#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <vector>
using namespace std;
////////////
struct datos
{
std::vector<float> simbolos;
std::vector<float> frecuencias;
int tamanodic;
} cd1;
/////////////////////declaracion de funciones
datos histograma(vector<float> &traza);
void shannonfano(datos &vida);
int main()
{
FILE *archivo;
char caracter;
std::vector<float> ayudante;
std::vector<float> traza;
float ayuda;
char numPtr[1];
float por=5;
archivo = fopen("D:\\entrada10.txt","r");
if (archivo == NULL)
{
printf("\nError de apertura del archivo. \n\n");
}
else
{
printf("\nEl contenido del archivo de prueba es \n\n");
while (feof(archivo) == 0)
{
caracter = fgetc(archivo);
numPtr[1]=caracter;
ayuda=float(numPtr[1]-48);
int kk=0;
ayudante.push_back(ayuda);
////////////////////////////////// aqui empezamos a tranformar
if (ayuda==-38)
{
if (ayudante[0]==-3)/////saber si es negativo
{
kk=1;
ayudante.erase (ayudante.begin());
}//////////
ayudante.pop_back();
int i=0;
float suma=0;
int cifras=0;/////dice cuantas cifras enteras tiene
while (i<ayudante.size()) ///////saber cuantas cifras enteras tiene
{
if(ayudante[i]==-2)//contador de cifras enteras
{
cifras=i;
i=ayudante.size();
}
else
{
i++;
cifras=i;
}
;
} //////////termina while
int ii=0;
int cifraaux=cifras;
float aux=0;
int k=0;
while (cifras>1)/////parte entera
{
aux=ayudante[ii];
k=cifras;
while (k>1) ///////multiplicaciones parte entera
{
aux=aux*10;
k--;
}
cifras--;
ii++;
suma=suma+aux;
}
suma=suma+ayudante[ii];
int deci=ayudante.size()-cifraaux-1;
ii=ayudante.size()-1;
while (deci>0)////parte decimal
{
aux=ayudante[ii];
k=deci;
while(k>0)///haciendo decimales
{
aux=aux/10;
k--;
}
deci--;
ii--;
suma=suma+aux;
}
if (kk==1)/////////signo negativo
{
traza.push_back(suma*-1);
}
else
{
traza.push_back(suma);
}
ayudante.clear();
}
//////////////////////////////////termina transformacion
}
}
fclose(archivo);
/////////////////////FUNCIONES%%%%%%%%%%%%%
histograma (traza);
cout<<"\n="<<cd1.tamanodic;
shannonfano(cd1);
getch();
}
//////////funcion HISTOGRAMA
////////%%%%%%%%%%&&&&&&&&&&&
datos histograma(vector<float> &traza)
{
//cargamos el primer valor
int contfre=0;
cd1.simbolos.push_back(traza[0]);
for (int ii=0; ii<traza.size(); ii++)
{
if (traza[ii]==traza[0])
{
contfre++;
}
}
cd1.frecuencias.push_back(contfre);
for (int i=1; i<traza.size(); i++)
{
int cont=0;
int contfre=0;
for (int ii=0; ii<cd1.simbolos.size(); ii++)
{
if (traza[i]==cd1.simbolos[ii])
{
cont++;
break;
}
}
if (cont==0)
{
cd1.simbolos.push_back(traza[i]);
for (int ii=i; ii<traza.size(); ii++)
{
if (traza[ii]==traza[i])
{
contfre++;
}
}
cd1.frecuencias.push_back(contfre);
}
}
cd1.tamanodic=cd1.simbolos.size();
for(int ii=0; ii<cd1.simbolos.size(); ii++)
{
cout<<"\n simbolos["<<ii<<"]="<<cd1.simbolos[ii];
cout<<"\n frecuencias["<<ii<<"]="<<cd1.frecuencias[ii];
}
float sumama=0;
for(int ii=0; ii<cd1.simbolos.size(); ii++)
{
sumama=sumama+cd1.frecuencias[ii];
}
cout<<"\n sumama="<<sumama;
return cd1;
}
///////////FUNCION SHANNON_FANO
///////////////////////////&&&&&&&&&&&&%%%%%%%%%%%%%%%
void shannonfano(datos &vida)
{
std::vector<float> ayudante;//copia de los simbolos
//%%%%%%%%%%%%
int pp=vida.tamanodic;
float masayuda=0;
for (int i=0; i<pp; i++)
{
masayuda=vida.simbolos[i];
ayudante.push_back(masayuda);//
}
//%%%%%%%%%%
bool dic[vida.tamanodic][20];//dic=diccionario
for (int i=0; i<pp; i++)
{
for(int ii=0; ii<20; ii++)
dic[i][ii]=0;
}
std::vector<int> numb;//numero de bits a tomar para la codificacion permite saber cuantos bits debo tomar para cada simbolo
std::vector<int> fin;// nos dice cual fue el simbolo que salio
int nci=0;
int contafin=0;//se guardara en fin
int numcol=0;//numero de columna en dic
int numfil=0;//numero de fila en dic
//%%%%%%%%%%%%%%%
std::vector<float> sfin; //las frecuencias pasan a este vector cuando ya se obtiene el codigo para el respectivo simbolo
std::vector<float> xfin;//el simbolo pasa a este vector cuando ya tiene un codigo asignado
int contaite=0;//numero de iteraciones, se guarda en numb
//%%%%%%%%%%%%%%%%%%%%%
//%%%%%%%%%%%%%%%%%%%%%
float temp;
float temp2;
//metodo burbuja en caso de que sea necesario ordenar
for (int i=0; i<pp; i++)
{
for (int j=i; j<pp; j++)
{
if (vida.frecuencias[i]<vida.frecuencias[j])
{
temp=vida.frecuencias[i];
temp2=vida.simbolos[i];
vida.frecuencias[i]=vida.frecuencias[j];
vida.simbolos[i]=vida.simbolos[j];
vida.frecuencias[j]=temp;
vida.simbolos[j]=temp2;
}
}
}
for(int ii=0; ii<100; ii++)
{
cout<<"\n simbolos["<<ii<<"]="<<vida.simbolos[ii];
cout<<"\n frecuencias["<<ii<<"]="<<vida.frecuencias[ii];
}
// aqui termina el ordenamiento de frecuencias y simbolos
float sum=0;
for (int i=0; i<vida.frecuencias.size(); i++)
{
sum=sum+vida.frecuencias[i];
}
cout<<"\n suma="<<sum;
// empezamos con el arbol
int z=1;
std::vector<float> c; //guarda la suma de frecuencias
std::vector<int> cc;//guarda cuantos simbolos suman cada frecuencia
c.push_back(sum);
cout<<"\n c[0]="<<c[0];
cc.push_back(vida.frecuencias.size());
cout<<"\n cc[0]="<<cc[0];
std::vector<float> d;
cout<<"\n maximo tamaño"<<d.max_size();
std::vector<int> dd;
//la idea del programa es ir observando los datos en c, para ir armando d,
//al finalizar el ciclo d se guarda en c y vuelve a empezar
int pa=0;
int XXX=0;
int compa=1;
int kkkkk=c.size();
for (;;)// ciclo para cambiar de celda
{
if (vida.frecuencias.empty())//el programa finaliza cuando el vector frecuencias esta vacio, osea q todos los simbolos ya tienen
//su respectivo codigo
{
break;
}
if (XXX>0) //para q copie d en c despues de la primera iteración
{
int kkkkk=d.size();
cout<<"\n kkk="<<kkkkk;
c.clear();
cc.clear();
for (int i=0; i<kkkkk; i++)
{
c.push_back(d[i]); //copio d en c
cc[i]=dd[i];// copio dd en cc
}
}
int kkkkk=d.size();
XXX++;
d.clear();
dd.clear();
int t=0;
int v=0;
int w=0;
int u=0;
for (;;)//en este ciclo se cambia de columna en el vector c
{
float tem=c[w];
u=0;
if (cc[w]>1)//necesitamos mas de un simbolo para dividir el valor guardado en c[w]
{
float sumpar=0;
while (sumpar<=tem/2)//operacion principal de shannon-fano, ir dividiendo en la mitad las frecuencias
{
sumpar=sumpar+vida.frecuencias[v];
u=u+1;
v=v+1;
}
if (u>1) //quito una para q qde siempre por debajo de la mitad o en la mitad
{
sumpar=sumpar-vida.frecuencias[v-1];
u=u-1;
}
d.push_back(sumpar);
dd.push_back(u);
d.push_back(c[w]-d[t]);
dd.push_back(cc[w]-dd[t]);
v=0;
for (int i=0; i<d.size(); i++)
{
v=v+dd[i];
}
t=t+2;
w=w+1;
if (w+1>kkkkk)
{
break;
}
}// termina if para armar d
else
{
w=w+1;
}
}//termina for para armar d
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// armamos los codigos %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
numfil=0;
for (int au=0; au<dd.size(); au++)
{
nci=dd[au];
int p=0;
int pop=1;
int qre=1;
//cout<<"\n numfil="<<numfil;
while (p<nci)
{
while (pop<=fin.size())//buscamos los simbolos que ya tienen un codigo, para no poner bits en sus codigos
{
if (numfil==fin[pop-1])
{
cout<<"\n no entre a fila="<<numfil;
numfil++;
pop=1;
}
else
{
pop++;
}
qre++;
}
int rem=au%2;//miramos si la posicion es par o impar, asi sabemos si debemos poner 0 o 1
if (rem==0)
{
//cout<<"\n numfil="<<numfil;
dic[numfil][numcol]=0;
}
else
{
dic[numfil][numcol]=1;
}
numfil++;
p++;
}
}
numcol++;
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//armando vectores finales
float pot=0;//para sfin
float potx=0;//para xfin
int knk=dd.size();
int gigo=0;
int sumita=0;
contaite++;
for (int i=0; i<knk; i++) //en esta parte eliminamos los simbolos que ya tienen un codigo, y los copiamos en xfin, al igual
// su respectiva frecuencia se copia en sfin
{
if (dd[gigo]==1)
{
if (gigo==0)
{
pot=vida.frecuencias[0];
potx=vida.simbolos[0];
sfin.push_back(pot);
xfin.push_back(potx);
vida.simbolos.erase (vida.simbolos.begin());
vida.frecuencias.erase (vida.frecuencias.begin());
dd.erase (dd.begin());
d.erase(d.begin());
int ayuda=0;
while (ayudante[ayuda]!=potx)//busca la posicion en la que se encuentra el simbolo a sacar
{
ayuda++;
}
numb.push_back(contaite);
fin.push_back(ayuda);//fin nos dice las filas de dic a las cuales no les debemos poner mas bits
}
else
{
sumita=0;
for (int i=0; i<gigo; i++)
{
sumita=sumita+dd[i];
}
pot=vida.frecuencias[sumita];
potx=vida.simbolos[sumita];
sfin.push_back(pot);
xfin.push_back(potx);
vida.simbolos.erase (vida.simbolos.begin()+sumita);
vida.frecuencias.erase (vida.frecuencias.begin()+sumita);
dd.erase (dd.begin()+gigo);
d.erase(d.begin()+gigo);
numb.push_back(contaite);//numb nos dice el numero de bits que tiene cada codigo
int ayuda=0;
while (ayudante[ayuda]!=potx)
{
ayuda++;
}
fin.push_back(ayuda);
}
}
else
{
gigo++;
}
}
for(int ii=0; ii<xfin.size(); ii++)
{
cout<<"\n xfin["<<ii<<"]="<<xfin[ii];
}
for(int ii=0; ii<xfin.size(); ii++)
{
cout<<"\n numb["<<ii<<"]="<<numb[ii];
}
}
int funca=0;
}