#include<stdarg.h>
#include<stdlib.h>
#include<stddef.h>
#include<stdio.h>
#include<string.h>
#include<math.h>

#define MAX_LINE_LENGTH 160000
#define INT_MAX 10000

void lookk();
void kk(int fuera);
float disn(long int pos1,long int pos2);
int getlabsam(FILE *fp, int *dim, float ***sample,char ***labels, int *nlabels, int **sample_labels);

float **datos,**tdatos;
int *datclas,*tdatclas;
int muestras,dim,clases,tclases,tdim,tmuestras;
char *prog;
char **labels,**tlabels;
int *in,kv;
float pc[1000];


void memtest(void *ptr)
{
  if (ptr==NULL)
    {
      fprintf(stderr,"%s: insufficient memory\n",prog);
      exit(EXIT_FAILURE);
    }
}

int main(int argc,char *argv[],char *env[])
{
 FILE *fe; 
 
 
 dim=0;
 prog=argv[0];

 fe=fopen(argv[1],"r");
 if (fe==NULL) {
  fprintf(stderr,"Error abriendo fichero.\n");
  exit(1);
 }
 muestras=getlabsam(fe,&dim,&datos,&labels,&clases,&datclas);
 fclose(fe);
 fprintf(stderr,"TR: %d muestras %d dim %d clases\n",muestras,dim,clases);
 
 fe=fopen(argv[2],"r");
 if (fe==NULL) {
  fprintf(stderr,"Error abriendo fichero.\n");
  exit(1);
 }
 tmuestras=getlabsam(fe,&tdim,&tdatos,&tlabels,&tclases,&tdatclas);
 fclose(fe);
 fprintf(stderr,"TS: %d muestras %d dim %d clases\n",tmuestras,tdim,tclases);
 
 if (dim!=tdim) {
   fprintf(stderr,"Error dimensiones distintas\n");
   exit(1);
 }

 kv=atoi(argv[3]);
 fprintf(stderr,"%d vecinos\n",kv);

 in=(int *)malloc(muestras*sizeof(int));

 
 lookk();
 
  
 return 0;

}



void lookk()
{
 int i,j,clase,acierto;

 for(i=1;i<kv;i++) 
   pc[i]=0;

 for(i=0;i<tmuestras;i++) {
   kk(i);
 } 

 
 for(i=1;i<=kv;i++) 
   printf("kv= %d error= %f\n",i,100.0-pc[i]*100/(float)tmuestras);

}



void kk(int fuera)  
{
  int i,j,l,k,indmin,indmax,max,clase[1000],cc[1000];
  float dmin[1000],dis;
 
 
  for(i=0;i<kv;i++) dmin[i]=100000000.0;
  

  for(i=0;i<muestras;i++) {
    dis=disn(fuera,i);
    for(j=0;j<kv;j++)
      if(dis<dmin[j]) {
	for(l=kv-1;l>j;l--) {
	  dmin[l]=dmin[l-1];
	  clase[l]=clase[l-1];
	}
	clase[j]=datclas[i];
	dmin[j]=dis;
	j=kv; /* Acabar */
      }
  }
  
   
  for(k=1;k<=kv;k++) {
    
    for(j=0;j<clases;j++) cc[j]=0;
  
    for(j=0;j<k;j++) cc[clase[j]]++;

    max=-1;
    for(i=0;i<k;i++) 
      if (cc[clase[i]]>max) {
	max=cc[clase[i]];
	indmax=clase[i];
      }

    if (!strcmp(labels[indmax],tlabels[tdatclas[fuera]])) 
      pc[k]++;
  }

}



float disn(long int pos1,long int pos2)
{

 float dis;
 int i;

 dis=0;
 for(i=0;i<dim;i++) 
  dis+=(tdatos[pos1][i]-datos[pos2][i])*(tdatos[pos1][i]-datos[pos2][i]);
 return sqrt(dis);
}




int getlabsam(FILE *fp, int *dim, float ***sample,
              char ***labels, int *nlabels, int **sample_labels)
{
  char line[MAX_LINE_LENGTH],*np,*endp,**labs=NULL;
  int d=(*dim>0)?(*dim):INT_MAX,n=0,nlabs=0,*samlabs=NULL,i;
  float **sam=NULL,f;

  while (fgets(line,MAX_LINE_LENGTH,fp)!=NULL)
    {
      for (i=0,strtod(np=line,&endp);i<d && np!=endp;i++,strtod(np=endp,&endp))
        ;
      for (;*np!='\0' && isspace(*np);np++)
        ;
      if (!i || (*np=='\0' && !(--i)))
        {
          fprintf(stderr,"%s: ignoring: %s",prog,line);
          continue;
        }
      if (i<d) d=i;
      /*fprintf(stderr,"%s: setting dim to %d\n",prog,d=i);*/
      memtest(sam=(float **)realloc((void *)sam,++n*sizeof(float *)));
      memtest(sam[n-1]=(float *)malloc(d*sizeof(float)));
      for (i=0,f=strtod(np=line,&endp);i<d;i++,f=strtod(np=endp,&endp))
        sam[n-1][i]=f;
      memtest(samlabs=(int *)realloc((void *)samlabs,n*sizeof(int)));
      for (;*np!='\0' && isspace(*np);np++)
        ;
      for (endp=np+strlen(np)-1;endp!=np && isspace(*endp);endp--)
        ;
      *++endp='\0';
      for (i=0;i<nlabs;i++)
        if (!strcmp(np,labs[i]))
          break;
      if (i==nlabs)
        {
          memtest(labs=(char **)realloc((void *)labs,++nlabs*sizeof(char *)));
          memtest(labs[i]=(char *)malloc((endp-np+1)*sizeof(char)));
          strcpy(labs[i],np);
        }
      samlabs[n-1]=i;
    }
  *dim=d;
  *sample=sam;
  *labels=labs;
  *nlabels=nlabs;
  *sample_labels=samlabs;
  return n;
}












