#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int T; int dx[4096], dy[4096]; double h[4096];
static int gcd(int a,int b){ while(b){int t=a%b;a=b;b=t;} return a; }
int cmpd(const void*a,const void*b){double x=*(double*)a,y=*(double*)b;return x<y?-1:x>y;}
int main(int argc,char**argv){
  FILE*f=fopen(argv[1],"r"); while(fscanf(f,"%d %d %lf",&dx[T],&dy[T],&h[T])==3)T++;
  int N0=atoi(argv[2]), N1=atoi(argv[3]); int dump=argc>4;
  double gbest=1e9; int gA=0,gB=0,gN=0;
  for(int N=N0;N<=N1;N++){
    double*H2=malloc(sizeof(double)*N*N); double*w=malloc(sizeof(double)*N);
    for(int b=0;b<N;b++)for(int a=0;a<N;a++){ double re=0,im=0; for(int i=0;i<T;i++){ long ph=((long)a*dx[i]+(long)b*dy[i])%N; if(ph<0)ph+=N; double t=2*M_PI*ph/N; re+=h[i]*cos(t); im+=h[i]*sin(t);} H2[b*N+a]=re*re+im*im; }
    for(int m=1;m<N;m++){ double s=sin(M_PI*m/N); w[m]=1/(2.0*N*N*s*s); }
    double best=1e9; int bA=0,bB=0; double*all=dump?malloc(sizeof(double)*N*N):0; long cnt=0;
    for(int B=0;B<N;B++)for(int A=0;A<N;A++){
      if(gcd(gcd(A,B),N)!=1) continue;
      double J=1/(12.0*N*N); int a=0,b=0;
      for(int m=1;m<N;m++){ a+=A; if(a>=N)a-=N; b+=B; if(b>=N)b-=N; J+=H2[b*N+a]*w[m]; }
      if(dump) all[cnt]=sqrt(J); cnt++;
      if(J<best){best=J;bA=A;bB=B;}
    }
    if(sqrt(best)<gbest-1e-12){gbest=sqrt(best);gA=bA;gB=bB;gN=N; printf("record N=%d (%d,%d) rms %.5f\n",N,bA,bB,gbest);}
    if(dump){ qsort(all,cnt,sizeof(double),cmpd); printf("N=%d count %ld best %.5f median %.5f worst %.5f\n",N,cnt,all[0],(all[cnt/2-1]+all[cnt/2])/2,all[cnt-1]);
      double r=atof(argv[4]); long below=0; for(long i=0;i<cnt;i++) if(all[i]>r) below++; printf("frac worse than %.5f: %.4f\n", r, (double)below/cnt); }
    free(H2);free(w);
  }
  printf("global best (%d,%d)/%d %.5f\n",gA,gB,gN,gbest);
}
