#define NUMS 3
long long d, u;
long long max_u;
int delta;
time_t start_time;
char strd[5*NUMS+1];
char stru[5*NUMS+2];
double err=1.0;
double twotimes64;
long long best_d, best_u;
int6 PI;
int6 N_PI[5*NUMS+1];
int6 NA1_PI[5*NUMS+1];
//dst=10*src
void time10(int6 *dst, int6 *src)
{
long long x0=src->x[0];
long long x1=src->x[1];
long long x2=src->x[2];
long long x3=src->x[3];
long long x4=src->x[4];
long long x5=src->x[5];
long long r;
long long c;
r=(x0<<1)+(x0<<3);
c=r>>32;
dst->x[0]=(unsigned)r;
r=(x1<<1)+(x1<<3)+c;
c=r>>32;
dst->x[1]=(unsigned)r;
r=(x2<<1)+(x2<<3)+c;
c=r>>32;
dst->x[2]=(unsigned)r;
r=(x3<<1)+(x3<<3)+c;
c=r>>32;
dst->x[3]=(unsigned)r;
r=(x4<<1)+(x4<<3)+c;
c=r>>32;
dst->x[4]=(unsigned)r;
r=(x5<<1)+(x5<<3)+c;
c=r>>32;
dst->x[5]=(unsigned)r;
}
int test(int L){
long long lu,uu;
int count[10];
int i;
lu = *(long long *)&N_PI[L-1].x[4];//Get the lower bound of u
uu = *(long long *)&NA1_PI[L-1].x[4];//Get the upper bound of u
if(uu>=max_u)uu=max_u-1;
delta=0;
while(lu<=uu){
sprintf(stru,"%*lld",L,lu);
memset(count,0,sizeof(count));
for(i=0;i<L;i++){
count[stru[i]-'0']++;
count[strd[i]-'0']++;
}
for(i=0;i<10&&count[i]<=NUMS;i++);
if(i>=10)return 1;
++lu;
++delta;
}
return 0;
}
void calc(){
double the_err;
unsigned x;
unsigned long long tail;
tail = *(unsigned long long *)&N_PI[5*NUMS-1].x[2];
// if(x==0&&delta==0||
// x==0xFFFFFFFF&&delta==1){
d/=10;
the_err=tail/twotimes64;
the_err-=delta;
the_err/=d;
the_err=fabs(the_err);
if(the_err<err){
err=the_err;
sscanf(stru,"%lld",&best_u);
best_d=d;
fprintf(stderr,"%lld/%lld,err=%g\n",best_u,best_d,err);
}
d*=10;
// }
}
void enum_num(int L){
int i,start,end;
if(L>=5*NUMS){
calc();
return;
}
if(L==3){
time_t now_time = time(NULL);
fprintf(stderr,"%c%c%c:\t%d seconds\n",strd[0],strd[1],strd[2], now_time-start_time);
}
start=(L==0);
end = (L==0)?3:9;
if(L>0){
time10(&N_PI[L],&N_PI[L-1]);//Initialize to d*Pi
}else{
memcpy(&N_PI[0],&PI,sizeof(N_PI[0]));//Initialize = 1*Pi since start from 1.
d=1;
max_u=10;
}
memcpy(&NA1_PI[L],&N_PI[L],sizeof(N_PI[L]));
add_by_pi(&NA1_PI[L]);//Initialize to (d+1)*Pi
for(i=start;i<=end;i++){
strd[L]=i+'0';
strd[L+1]='\0';
if(test(L+1)){
d*=10LL;
max_u*=10LL;
enum_num(L+1);
d/=10LL;
max_u/=10LL;
}
d++;
memcpy(&N_PI[L],&NA1_PI[L],sizeof(N_PI[L]));
add_by_pi(&NA1_PI[L]);
}
d-=(end-start+1);
}
int main(int argc, char *argv[])
{
int i;
start_time = time(NULL);
init_PI();
twotimes64=1.0;
for(i=0;i<16;i++)twotimes64*=16;
if(argc<=1){
enum_num(0);
}else{
int v=atoi(argv[1]);
if(v<10||v>31){
fprintf(stderr,"The parameter should be between 10 and 31\n");
return -1;
}
sprintf(strd,"%02d",v);
d=v*10;
max_u=1000;
{///Preparing N_PI[1];that's v*PI
memcpy(&N_PI[1],&PI,sizeof(PI));
for(i=2;i<=v/10;i++)
add_by_pi(&N_PI[1]);
time10(&N_PI[1],&N_PI[1]);
for(i=0;i<v%10;i++)
add_by_pi(&N_PI[1]);///Insert more call to add_by_pi when strd[0] is larger than 2
}
enum_num(2);
}
printf("Result:%d/%d\n",best_u,best_d);
}