Permalink
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
minimal-elements-of-the-prime-numbers/code/famk.cc
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
576 lines (546 sloc)
22.3 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <list> | |
#include <cmath> | |
#include <string> | |
#include <random> | |
#include <algorithm> | |
#include <vector> | |
#include <iostream> | |
#include <fstream> | |
#include <time.h> | |
#include <stdlib.h> | |
#include <gmpxx.h> | |
#include <gmp.h> | |
#define cyclemax 24 | |
using namespace std; | |
// code base mxlg | |
// tries to extend the current kernel for base with primes up to length mxlg, while starting with the families provided on the standard input file | |
// new found primes are gathered in a file newprimes{base}-suffix | |
// and families to be still analyzed are gathered in a file left{base}-suffix | |
// details of the exploration are send to the standard output | |
char tr[128]; int w[128]; | |
using family=vector <string>; | |
using sint=long unsigned int; // std::vector<std::__cxx11::basic_string<char> >::size_type; | |
vector <string> found; | |
ifstream kern; ofstream result,reject,court; | |
sint b; | |
vector <sint> fact; string covering; | |
clock_t cpustarttime,cputime; | |
mpz_class nt,nprime,nlong,n1; | |
sint k,lgmax,nbsmall; | |
mpz_t rtt,rt1,rt2; | |
random_device rd; | |
mt19937 gen(rd()); // set random gen | |
string s10(mpz_class x) | |
{mpz_class y=x; int r; string s=""; | |
while (y!=0){r=mpz_class{y%10}.get_si();y=y/10;s=tr[r]+s;} | |
return s; | |
} | |
string sb(mpz_class x) | |
{mpz_class y=x; int r; string s="";if(x==0)return "0"; | |
while (y!=0){r=mpz_class{y%b}.get_si();y=y/b;s=tr[r]+s;} | |
return s; | |
} | |
string familystrip(family f) | |
{string ss; sint i; | |
ss=""; | |
for(i=0;i<f.size();i=i+2)ss=ss+f[i]; | |
return(ss); | |
} | |
string stringf(family f) | |
{sint i; string s;if(f.size()==1)return f[0]; | |
if(f.size()==1){s=f[0];return s;} | |
for(i=0;i<f.size()-2;i=i+2)s=s+f[i]+"{"+f[i+1]+"}"; | |
s=s+f[i]; | |
return s; | |
} | |
long long gcd(long long i,long long j) | |
{long long ii,jj,kk; if(i==0)return j;if(j==0)return i; | |
if(j>i){ii=j;jj=i;} else {ii=i;jj=j;} | |
while(jj!=0){kk=ii%jj;ii=jj;jj=kk;} | |
return ii;} | |
mpz_class gcd(mpz_class i,mpz_class j) | |
{mpz_class ii,jj,kk; if(i==0)return j;if(j==0)return i; | |
if(j>i){ii=j;jj=i;} else {ii=i;jj=j;} | |
while(jj!=0){kk=ii%jj;ii=jj;jj=kk;} | |
return ii;} | |
int min( int i, int j) | |
{if(i<=j)return i;else return j;} | |
void buildfact() | |
{sint kk,n; bool ok; | |
fact.push_back(2);fact.push_back(3);fact.push_back(5); | |
for(n=7;n<b*b*b;n++) | |
{ok=true;for(kk=0;fact[kk]*fact[kk]<=n;kk++) | |
if(n%fact[kk]==0){ok=false;break;} | |
if(ok){fact.push_back(n);} | |
} | |
for(nbsmall=0;fact[nbsmall]<b*b;nbsmall++)continue; | |
} | |
bool cover(string el) | |
// checks if some member of found is a substring of el | |
{sint i,j,it; | |
for(it=0;it!=found.size();it++) | |
{if(el==found[it]){covering=found[it];return true;} | |
if(el.length()<found[it].length())continue; | |
i=0;j=0; | |
while(i<el.length()) | |
{if(el[i]==(found[it])[j]) | |
{i++;j++;if(j>=(found[it]).length()){covering=found[it];return true;} | |
if(i>=el.length())break; | |
} | |
else {i++;if(i>=el.length())break;} | |
} | |
} | |
return false; | |
} | |
bool newprime(string s) | |
{sint i; mpz_class n1=0; | |
for(i=0;i<s.length();i++)n1=n1*b+w[s[i]]; | |
if(mpz_probab_prime_p(n1.get_mpz_t(),50)>0) | |
{nprime++;court<<s<<"\n";found.push_back(s);court.flush();return true;} | |
else {return false;} | |
} | |
bool difsq(string s1,int y,string s2) | |
{sint i; mpz_class bb,bx,xb,yb,zy,gg,xx,yy,zz,z1,z2; bool test; | |
xb=0;yb=0;bx=1;bb=b;zy=y; | |
if(!mpz_root(rtt,bb.get_mpz_t(),2))return false; | |
for(i=0;i<s1.size();i++)xb=xb*b+w[s1[i]]; | |
for(i=0;i<s2.size();i++)yb=yb*b+w[s2[i]]; | |
for(i=0;i<s2.size();i++)bx=bx*b; | |
gg=gcd(zy,bb-1); | |
xx=(y+(b-1)*xb)/gg; | |
if(!mpz_root(rtt,xx.get_mpz_t(),2))return false; | |
yy=(bx*y-(b-1)*yb)/gg; | |
if(!mpz_root(rtt,yy.get_mpz_t(),2))return false; | |
z2=mpz_class(rtt); | |
zz=bx*xx; | |
mpz_root(rtt,zz.get_mpz_t(),2); | |
z1=mpz_class(rtt); | |
test=(z1-z2)>((b-1)/gg); | |
if(test) | |
{cout<<s1<<"{"<<tr[y]<<"}"<<s2<<" is a difference of squares " | |
<<b<<", "<<xx<<" and "<<yy<<"\n"; return true;} | |
return false; | |
} | |
bool p4p4p4b(string s1,int y,string s2) | |
// checks if we have a factorisation of x^4+4.y^4 for {d} | |
{sint i; mpz_class bb,bx,xb,yb,zy,gg,xx,yy,zz,z1,z2; bool t1,t2; | |
xb=0;yb=0;bx=1;bb=b;zy=y; | |
if(!mpz_root(rtt,bb.get_mpz_t(),4))return false; | |
for(i=0;i<s1.size();i++)xb=xb*b+w[s1[i]]; | |
for(i=0;i<s2.size();i++)yb=yb*b+w[s2[i]]; | |
for(i=0;i<s2.size();i++)bx=bx*b; | |
gg=gcd(zy,bb-1); | |
xx=(y+(b-1)*xb)/gg; | |
yy=((b-1)*yb-bx*y)/gg;if(yy<=0)return false; | |
if(xx%4==0){z1=xx/4; t1=mpz_root(rt1,z1.get_mpz_t(),4); | |
t2=mpz_root(rt2,yy.get_mpz_t(),4); | |
if(t1&&t2) | |
{cout<<s1<<"{"<<sb(y)<<"}"<<s2<<" has a Germain's factorisation (" | |
<<z1<<","<<yy<<")\n";return true;} | |
} | |
if(yy%4==0){z2=yy/4; t1=mpz_root(rt2,z2.get_mpz_t(),4); | |
t2=mpz_root(rt2,xx.get_mpz_t(),4); | |
if(t1&&t2) | |
{cout<<s1<<"{"<<sb(y)<<"}"<<s2<<" has a Germain's factorisation (" | |
<<xx<<","<<z2<<")\n";return true;} | |
} | |
return false; | |
} | |
bool p4p4p4bb(string s1,string sddk,string s2) | |
// checks if we have a factorisation of x^4+4.y^4 for {dd} or {dddd} | |
{sint i,k; mpz_class bb,bx,xb,yb,y,gg,xx,yy,zz,z1,z2; bool t1,t2; | |
xb=0;yb=0;bx=1;y=0;k=sddk.size();for(i=0;i<k;i++)y=y*b+w[sddk[i]]; | |
bb=b;if(k==2)if(!mpz_root(rtt,bb.get_mpz_t(),2))return false; | |
if(s2.size()%k!=0) | |
{for(i=0;i<s2.size()%k;i++){s2=sddk[0]+s2; | |
if(cover(s1+s2))return false; | |
if(newprime(s1+s2))return false;} | |
for(i=i;i<k;i++){s1=s1+sddk[0]; | |
if(cover(s1+s2))return false; | |
if(newprime(s1+s2))return false;} | |
} | |
for(i=0;i<s1.size();i++)xb=xb*b+w[s1[i]]; | |
for(i=0;i<s2.size();i++)yb=yb*b+w[s2[i]]; | |
for(i=0;i<s2.size();i++)bx=bx*b; | |
gg=gcd(y,bx-1); | |
xx=(y+(bx-1)*xb)/gg; | |
yy=((bx-1)*yb-bx*y)/gg;if(yy<=0)return false; | |
if(xx%4==0){z1=xx/4; t1=mpz_root(rt1,z1.get_mpz_t(),4); | |
t2=mpz_root(rt2,yy.get_mpz_t(),4); | |
if(t1&&t2) | |
{cout<<s1<<"{"<<sb(y)<<"}"<<s2<<" has a Germain's factorisation (" | |
<<z1<<","<<yy<<")\n";return true;} | |
} | |
if(yy%4==0){z2=yy/4; t1=mpz_root(rt2,z2.get_mpz_t(),4); | |
t2=mpz_root(rt2,xx.get_mpz_t(),4); | |
if(t1&&t2) | |
{cout<<s1<<"{"<<sb(y)<<"}"<<s2<<" has a Germain's factorisation (" | |
<<xx<<","<<z2<<")\n";return true;} | |
} | |
return false; | |
} | |
bool difpowb(string s1,int y,string s2,int k) | |
{sint i; mpz_class bb,bx,xb,yb,zy,gg,xx,yy,zz,rt,rtk,z1,z2; bool test; | |
xb=0;yb=0;bx=1;bb=b;zy=y; | |
if(!mpz_root(rtt,bb.get_mpz_t(),k))return false; | |
for(i=0;i<s1.size();i++)xb=xb*b+w[s1[i]]; | |
for(i=0;i<s2.size();i++)yb=yb*b+w[s2[i]]; | |
for(i=0;i<s2.size();i++)bx=bx*b; | |
gg=gcd(zy,bb-1); | |
xx=(y+(b-1)*xb)/gg; | |
if(!mpz_root(rtt,xx.get_mpz_t(),k))return false; | |
yy=(bx*y-(b-1)*yb)/gg; | |
if(yy<0&&k%2==0)return false; | |
if(!mpz_root(rtt,yy.get_mpz_t(),k))return false; | |
zz=bx*xx; | |
mpz_root(rt1,zz.get_mpz_t(),k);z1=mpz_class(rt1); | |
mpz_root(rt2,yy.get_mpz_t(),k);z2=mpz_class(rt2); | |
test=(z1-z2)>((b-1)/gg); | |
if(test) | |
{cout<<s1<<"{"<<sb(y)<<"}"<<s2<<" is a difference of " | |
<<k<<"th powers: "<<b<<"^*."<<xx<<" and "<<yy<<"\n"; | |
return true;} | |
return false; | |
} | |
bool difpowbb(string s1,string sddk,string s2) | |
{sint i,k; mpz_class bb,bx,xb,yb,y,gg,xx,yy,zz,rt,rtk,z1,z2; bool test; | |
xb=0;yb=0;bx=1;y=0;k=sddk.size();for(i=0;i<k;i++)y=y*b+w[sddk[i]]; | |
bb=1;for(i=0;i<k;i++){bb=bb*b;} | |
if(s2.size()%k!=0) | |
{for(i=0;i<s2.size()%k;i++){s2=sddk[0]+s2; | |
if(cover(s1+s2))return false; | |
if(newprime(s1+s2))return false;} | |
for(i=i;i<k;i++){s1=s1+sddk[0]; | |
if(cover(s1+s2))return false; | |
if(newprime(s1+s2))return false;} | |
} | |
for(i=0;i<s1.size();i++)xb=xb*b+w[s1[i]]; | |
for(i=0;i<s2.size();i++)yb=yb*b+w[s2[i]]; | |
for(i=0;i<s2.size();i++)bx=bx*b; | |
gg=gcd(y,bb-1); | |
xx=(y+(bb-1)*xb)/gg; | |
if(!mpz_root(rtt,xx.get_mpz_t(),k)){return false;} | |
yy=(bx*y-(bb-1)*yb)/gg; | |
if(yy<0&&k%2==0)return false; | |
if(!mpz_root(rtt,yy.get_mpz_t(),k))return false; | |
zz=bx*xx; | |
mpz_root(rt1,zz.get_mpz_t(),k);z1=mpz_class(rt1); | |
mpz_root(rt2,yy.get_mpz_t(),k);z2=mpz_class(rt2); | |
test=(z1-z2)>((bb-1)/gg); | |
if(test) | |
{cout<<s1<<"{"<<sb(y)<<"}"<<s2<<" is a difference of " | |
<<k<<"th powers: "<<bb<<", "<<xx<<" and "<<yy<<"\n"; | |
return true;} | |
return false; | |
} | |
bool smallfactor(family f) | |
{sint i,ii,i1,i2;mpz_class n1; | |
for(ii=0;ii<nbsmall;ii++) | |
{i=fact[ii];n1=0; | |
for(i1=0;i1<f.size();i1++) | |
{if(i1%2==0) | |
{for(i2=0;i2<f[i1].size();i2++)n1=(n1*b+w[f[i1][i2]])%i; | |
} | |
else | |
{for(i2=0;i2<f[i1].size();i2++){if(n1!=((n1*b+w[f[i1][i2]])%i))break;} | |
if(i2!=f[i1].size())break; | |
} | |
} | |
if(i1!=f.size())continue; | |
if(n1==0){cout<<"small factor "<<i<<" for "<<stringf(f)<<"\n";return true;} | |
} | |
if(f.size()==3)if(f[1].size()==1) | |
{for(i=2;i<cyclemax;i++)if(difpowb(f[0],w[f[1][0]],f[2],i))return true; | |
if(p4p4p4b(f[0],w[f[1][0]],f[2]))return true; | |
} | |
return false; | |
} | |
bool cyclicfactors(family f) | |
{ sint i,j,k,ii,i1,i2,iff;mpz_class n1,dk,ddk; string cycles[cyclemax]; | |
string pj,sddk; family ff; | |
for(i=1;i<f.size();i=i+2)if(f[i].size()==1) | |
{dk=1;ddk=0;sddk=""; | |
for(k=1;k<=cyclemax;k++) | |
{pj="";dk=dk*b;ddk=ddk*b+w[f[i][0]];sddk+=f[i]; | |
for(j=0;j<k;j++) // fam= fam1(pj){dk}fam2 | |
{ff=f;ff[i-1]=f[i-1]+pj; pj+=f[i]; | |
for(ii=0;ii<nbsmall;ii++) | |
{iff=fact[ii];n1=0; | |
for(i1=0;i1<ff.size();i1++) | |
{if(i1%2==0) | |
{for(i2=0;i2<ff[i1].size();i2++)n1=(n1*b+w[ff[i1][i2]])%iff; | |
} | |
else | |
{if(i1==i){if(n1!=((n1*dk+ddk)%iff))break;} else | |
{for(i2=0;i2<f[i1].size();i2++){if(n1!=((n1*b+w[f[i1][i2]])%iff))break;} | |
if(i2!=f[i1].size())break; | |
} | |
} | |
} | |
if(i1==ff.size()&&n1==0){cycles[j]=sb(iff);break;} | |
} | |
if(ii<nbsmall)continue; | |
if(f.size()!=3)break; | |
if(k>1&&difpowbb(ff[0],sddk,ff[2])) | |
{cycles[j]="diff of kth powers";continue;} | |
if((k==2||k==4)&&p4p4p4bb(ff[0],sddk,ff[2])) | |
{cycles[j]="Germain's rule";continue;} | |
break; | |
} | |
if(j==k){cout<<" cycle of factors of length "<<k<<" at position "<<i+1<<" :"; | |
for(j=0;j<k;j++){cout<<cycles[j]<<",";} | |
cout<<" for "<<stringf(f)<<"\n"; cout.flush(); return true; | |
} | |
} | |
} | |
return false; | |
} | |
bool dcyclfact(family f) | |
{if(f.size()<5)return false; | |
sint i1,i2,j1,j2,k1,k2,ii,ii2,iii,iff;mpz_class n1,dk1,dk2,ddk1,ddk2; | |
int cycles[cyclemax][cyclemax]; string pj1,pj2;family ff; | |
for(i1=1;i1<f.size();i1=i1+2)if(f[i1].size()==1) | |
for(i2=i1+2;i2<f.size();i2=i2+2)if(f[i2].size()==1) | |
{dk1=1;ddk1=0;ff=f; | |
for(k1=1;k1<cyclemax;k1++) | |
{pj1="";dk1=dk1*b;ddk1=ddk1*b+w[f[i1][0]]; | |
for(j1=0;j1<k1;j1++) // fam= fam1(pj1){dk1}fam2 | |
{ff[i1-1]=f[i1-1]+pj1; ff[i1]=sb(ddk1); dk2=1;ddk2=0;pj1=pj1+f[i1]; | |
for(k2=1;k2<cyclemax;k2++) | |
{pj2="";dk2=dk2*b;ddk2=ddk2*b+w[f[i2][0]]; | |
for(j2=0;j2<k2;j2++) // fam= fam1(pj1){dk1}fam2(pj2){dk2}fam3 | |
{ff[i2-1]=f[i2-1]+pj2; ff[i2]=sb(ddk2);pj2=pj2+f[i2]; | |
for(ii=0;ii<nbsmall;ii++) | |
{iff=fact[ii];n1=0; | |
for(iii=0;iii<ff.size();iii++) | |
{if(iii%2==0) | |
{for(ii2=0;ii2<ff[iii].size();ii2++) | |
n1=(n1*b+w[ff[iii][ii2]])%iff;} | |
else | |
{if(iii==i1){if(n1!=((n1*dk1+ddk1)%iff))break;} else | |
if(iii==i2){if(n1!=((n1*dk2+ddk2)%iff))break;} else | |
{for(ii2=0;ii2<f[iii].size();ii2++) | |
{if(n1!=((n1*b+w[f[iii][ii2]])%iff))break;} | |
if(ii2!=f[iii].size())break; } } } | |
if(iii==ff.size()&&n1==0){cycles[j1][j2]=iff;break;}} | |
if(ii==nbsmall)break;} | |
if(j2==k2)break;} | |
if(k2==cyclemax)break;} | |
if(j1==k1)break;} | |
if(k1!=cyclemax) | |
{cout<<" rectangular cycle of factors of length ("<<k1<<","<<k2<<") "; | |
cout<<"at positions (" <<i1<<","<<i2<<") :\n"; | |
for(j1=0;j1<k1;j1++) | |
{cout<<"(";for(j2=0;j2<k2;j2++)cout<<cycles[j1][j2]<<","; | |
cout<<")\n"; | |
} | |
return true; | |
} | |
} | |
return false; | |
} | |
bool par3(family f) // check if a ternary choice has cyclic even/odd factors | |
{if(f.size()<7)return false; | |
sint i1,i2,i3,j1,j2,j3,ii,ii2,iii,iff;mpz_class n1,dk1,dk2,ddk1,ddk2; | |
int cycles[2][2][2]; string pj1,pj2;family ff; | |
for(i1=1;i1<f.size();i1=i1+2)if(f[i1].size()==1) | |
for(i2=i1+2;i2<f.size();i2=i2+2)if(f[i2].size()==1) | |
for(i3=i2+2;i3<f.size();i3=i3+2)if(f[i3].size()==1) | |
{ | |
for(j1=0;j1<2;j1++){for(j2=0;j2<2;j2++){for(j3=0;j3<2;j3++) | |
{ff=f;ff[i1]=f[i1]+f[i1];ff[i2]=f[i2]+f[i2];ff[i3]=f[i3]+f[i3]; | |
if(j1==1)ff[i1-1]=f[i1-1]+f[i1]; | |
if(j2==1)ff[i2-1]=f[i2-1]+f[i2]; | |
if(j3==1)ff[i3-1]=f[i3-1]+f[i3]; | |
for(ii=0;ii<nbsmall;ii++) | |
{iff=fact[ii];n1=0; | |
for(iii=0;iii<ff.size();iii++) | |
{if(iii%2==0) | |
{for(ii2=0;ii2<ff[iii].size();ii2++) | |
n1=(n1*b+w[ff[iii][ii2]])%iff;} | |
else | |
{if(iii==i1){if(n1!=((n1*b*b+(b+1)*w[f[iii][0]])%iff))break;} else | |
if(iii==i2){if(n1!=((n1*b*b+(b+1)*w[f[iii][0]])%iff))break;} else | |
if(iii==i3){if(n1!=((n1*b*b+(b+1)*w[f[iii][0]])%iff))break;} else | |
{for(ii2=0;ii2<f[iii].size();ii2++) | |
if(n1!=((n1*b+w[f[iii][ii2]])%iff))break; | |
if(ii2!=f[iii].size())break; } } } | |
if(iii==ff.size()&&n1==0){ | |
cycles[j1][j2][j3]=iff;break;}} | |
if(ii==nbsmall)break;} | |
if(j3!=2)break;} if(j2!=2)break;} if(j1==2) | |
{cout<<" ternary even/odd factors at positions (" <<i1<<","<<i2<<","<<i3<<") for : "<<stringf(f)<<"===>\n"; | |
for(j1=0;j1<2;j1++) {cout<<"[";for(j2=0;j2<2;j2++){cout<<"(";for(j3=0;j3<2;j3++)cout<<cycles[j1][j2][j3]<<",";} | |
cout<<"),";} | |
cout<<"],";cout<<"\n"; return true;} | |
} | |
return false; | |
} | |
void handelf(family f) | |
{family ff,fff; string s,s1,s2,p,p1,p2; bool test; | |
sint i,j,l,ic,jc,ic1,ic2,lc1,lc2,jc1,jc2,i1,i2,j1,j2; | |
cout<<stringf(f)<<"\n";cout.flush();fff=f;nt++; | |
for(j=1;j<f.size();j=j+2) // clean choices | |
{p=""; | |
for(l=0;l<f[j].size();l++) | |
{ff=f;ff[j-1]=f[j-1]+f[j][l];s=familystrip(ff); | |
if(!cover(s))p.push_back(f[j][l]); | |
} | |
f[j]=p; | |
} | |
for(i=1;i<f.size();i=i+2)if(f[i].size()==0) // simplify void choices | |
{f[i-1]=f[i-1]+f[i+1];f.erase(f.begin()+i,f.begin()+i+2);i=i-2;} | |
for(i=1;i<f.size();i=i+2)if(f[i].size()==1&&f[i][0]==f[i+1][0]) | |
{f[i-1]=f[i-1]+f[i];f[i+1].erase(0,1);} // simplify {a}a into a{a} | |
if(f.size()!=1) | |
for(i=1;i<f.size()-2;i=i+2){ | |
if(f[i].size()==1&&f[i+1].size()==0&&f[i]==f[i+2]) | |
{f.erase(f.begin()+i+1,f.begin()+i+3);}} // simplify {a}""{a} into {a} | |
if(f!=fff){cout<<"=======> ";cout<<stringf(f)<<"\n";} | |
s=familystrip(f); | |
if(cover(s)){cout<<"covered by "<<covering<<"\n";return;} | |
if(newprime(s)){return;} | |
if(f.size()==1)return; // single string | |
if(smallfactor(f))return; | |
if(cyclicfactors(f))return; | |
if(dcyclfact(f))return; | |
if(par3(f))return; | |
if(s.size()>lgmax){cout<<"still to analyze (too long)\n";nlong++; | |
reject<<stringf(f)<<"\n";reject.flush();return;} | |
// if a digit must be repeated, repeat it, if not already very long | |
if(s.size()<=lgmax/2) | |
for(i=1;i<f.size();i=i+2)for(j=0;j<f[i].size();j++) | |
{ff=f;ff[i]=ff[i].erase(j,1);p=f[i][j]; | |
test=smallfactor(ff); | |
if(!test)test=cyclicfactors(ff); | |
if(!test)test=dcyclfact(ff); | |
if(!test)test=par3(ff); | |
if(test) | |
{if(f[i].size()==1){f[i-1]=f[i-1]+f[i];cout<<"needed extension ";handelf(f);return;} | |
ff.insert(ff.begin()+i+1,p);ff.insert(ff.begin()+i+2,f[i]); | |
cout<<"needed extension ";handelf(ff);return; | |
} | |
} | |
s=""; // if no covering | |
for(i=1;i<f.size();i=i+2) | |
{s=s+f[i-1];for(j=0;j<lgmax;j++)s=s+f[i];} | |
s=s+f.back();if(!cover(s)){cout<<"too long:"<<stringf(f)<<"\n"; | |
reject<<stringf(f)<<"\n";reject.flush();return;} | |
// search for a digit with minimal extension | |
lc1=1000;ic=1;jc=0; | |
for(i=1;i<f.size();i=i+2) | |
{s1="";s2=""; | |
for(j=0;j<i;j=j+2)s1=s1+f[j]; | |
for(j=i+1;j<f.size();j=j+2)s2=s2+f[j]; | |
for(l=0;l<f[i].size();l++) | |
{p=f[i][l];for(j=0;j<10;j++)p=p+p; | |
if(cover(s1+p+s2)){if(covering.size()<lc1){lc1=covering.size();ic=i;jc=l;}} | |
} | |
} | |
// search for a pair of options with a minimal covering | |
lc2=lc1; | |
for(i1=1;i1<f.size();i1=i1+2) for(i2=i1+2;i2<f.size();i2=i2+2) | |
for(j1=0;j1<f[i1].size();j1++) for(j2=0;j2<f[i2].size();j2++) | |
{ff=f; p1=f[i1][j1];for(j=0;j<10;j++)p1=p1+p1;p2=f[i2][j2];for(j=0;j<10;j++)p2=p2+p2; | |
ff[i1-1]=ff[i1-1]+p1;ff[i2-1]=ff[i2-1]+p2;s=familystrip(ff); | |
if(cover(s)){if(covering.size()<lc2){ic1=i1;ic2=i2;jc1=j1;jc2=j2;lc2=covering.size();}} | |
} | |
for(i1=1;i1<f.size();i1=i1+2) | |
for(j1=0;j1<f[i1].size();j1++) for(j2=j1+1;j2<f[i2].size();j2++) | |
{ff=f;i2=i1;p1=f[i1][j1];for(j=0;j<10;j++)p1=p1+p1;p2=f[i2][j2];for(j=0;j<10;j++)p2=p2+p2; | |
ff[i1-1]=f[i1-1]+p1+p2;s=familystrip(ff); | |
if(!cover(s))continue; | |
l=covering.size();if(l>=lc2)continue; | |
ff[i1-1]=f[i1-1]+p2+p1;s=familystrip(ff); | |
if(!cover(s))continue; | |
if(l<covering.size())l=covering.size(); | |
if(l>=lc2)continue; | |
ic1=i1;ic2=i2;jc1=j1;jc2=j2;lc2=l; | |
} | |
// handle selection | |
if(lc2>=lc1) // no pair is really interesting | |
{if(lc1==1000) // no digit is really selected: chose one randomly | |
{test=false; | |
if(f.size()>3){l=f.size()/2;uniform_int_distribution<> distri(0,l-1);test=true; | |
ic=1+2*(distri(gen));} | |
if(f[ic].length()>1){uniform_int_distribution<> distrj(0,f[ic].length()-1);jc=distrj(gen);test=true;} | |
if(test)cout<<"! "<<ic<<","<<jc<<"\n"; | |
} | |
ff=f;p=f[ic][jc];ff[ic].erase(jc,1); | |
cout<<"split1 "<<stringf(f)<<" without ("<<ic<<","<<f[ic][jc]<<")-ext="<<lc1<<"\n";handelf(ff); | |
cout<<"extend1 "<<stringf(f)<<" with ("<<ic<<","<<f[ic][jc]<<")\n"; | |
ff.insert(ff.begin()+ic+1,p);ff.insert(ff.begin()+ic+2,f[ic]); handelf(ff); | |
} | |
else // a pair should be handled | |
{p1=f[ic1][jc1];p2=f[ic2][jc2]; | |
ff=f;ff[ic2].erase(jc2,1);ff[ic1].erase(jc1,1); | |
cout<<"split2 "<<stringf(f)<<" without ("<<ic1<<","<<f[ic1][jc1]<<") and ("<<ic2<<","<<f[ic2][jc2]<<")-ext="<<lc2<<"\n"; | |
handelf(ff);fff=ff; | |
ff.insert(ff.begin()+ic1+1,p1);ff.insert(ff.begin()+ic1+2,ff[ic1]+f[ic1][jc1]); | |
cout<<"extend21 "<<stringf(f)<<" with ("<<ic1<<","<<f[ic1][jc1]<< | |
") and without ("<<ic2<<","<<f[ic2][jc2]<<")\n"; | |
handelf(ff);ff=fff; | |
ff.insert(ff.begin()+ic2+1,p2);ff.insert(ff.begin()+ic2+2,ff[ic2]+f[ic2][jc2]); | |
cout<<"extend22 "<<stringf(f)<<" with ("<<ic2<<","<<f[ic2][jc2]<< | |
") and without ("<<ic1<<","<<f[ic1][jc1]<<")\n"; | |
handelf(ff);ff=fff; | |
if(ic1!=ic2) | |
{ff.insert(ff.begin()+ic1+1,p1);ff.insert(ff.begin()+ic1+2,f[ic1]); | |
ff.insert(ff.begin()+ic2+3,p2);ff.insert(ff.begin()+ic2+4,f[ic2]); | |
cout<<"extend212 "<<stringf(f)<<" with ("<<ic1<<","<<f[ic1][jc1]<< | |
") and ("<<ic2<<","<<f[ic2][jc2]<<")\n"; | |
handelf(ff); | |
} else | |
{ff[ic1]=ff[ic1]+p2;ff.insert(ff.begin()+ic1+1,p1);ff.insert(ff.begin()+ic1+2,fff[ic1]+p1); | |
ff.insert(ff.begin()+ic2+3,p2);ff.insert(ff.begin()+ic2+4,f[ic2]); | |
cout<<"extend212 "<<stringf(f)<<" with ("<<ic1<<","<<f[ic1][jc1]<< | |
") and ("<<ic2<<","<<f[ic2][jc2]<<")\n"; | |
handelf(ff);ff=fff; | |
ff[ic1]=ff[ic1]+p1;ff.insert(ff.begin()+ic1+1,p2);ff.insert(ff.begin()+ic1+2,fff[ic2]+p2); | |
ff.insert(ff.begin()+ic2+3,p1);ff.insert(ff.begin()+ic2+4,f[ic1]); | |
cout<<"extend221 "<<stringf(f)<<" with ("<<ic1<<","<<f[ic1][jc2]<< | |
") and ("<<ic2<<","<<f[ic2][jc1]<<")\n"; | |
handelf(ff); | |
} | |
} | |
} // fin du traitement de la base | |
int main(int argc, char *argv[]) | |
{string ms,pref,prefms,p,ss,chunkl,chunkr; family f; | |
sint i,ilb,ilh,irb,irh,il,ir,j; | |
mpz_init(rtt); mpz_init(rt1); mpz_init(rt2); | |
ms=argv[1];b=atoi(argv[1]); lgmax=atoi(argv[2]); | |
pref="kernel"; prefms=pref+ms; | |
kern.open(prefms.c_str()); | |
pref="result"; prefms=pref+ms; | |
result.open(prefms.c_str(),ios::out); | |
pref="newprimes"; prefms=pref+ms; | |
court.open(prefms.c_str(),ios::out); | |
pref="left"; prefms=pref+ms; | |
reject.open(prefms.c_str(),ios::out); | |
for(char c='0';c<='9';c++){w[c]=0+c-'0';tr[0+c-'0']=c;} | |
for(char c='A';c<='Z';c++){w[c]=10+c-'A';tr[10+c-'A']=c;} | |
for(char c='a';c<='z';c++){w[c]=36+c-'a';tr[36+c-'a']=c;} | |
buildfact(); | |
cout<<"lgmax="<<lgmax<<"\n";cout.flush(); | |
found.clear();nt=0;nprime=0;nlong=0; | |
while(kern>>p) | |
{found.push_back(p); | |
} | |
// initialisation | |
cpustarttime=clock(); | |
while(cin>>p) | |
{f.clear();ss=""; | |
for(i=0;i<p.length();i++) | |
{if(p[i]=='{'||p[i]=='}'){f.push_back(ss);ss="";} else ss=ss+p[i];} | |
f.push_back(ss); | |
//construction of the familles to be explored | |
handelf(f); | |
} | |
cputime = clock()-cpustarttime; cputime=cputime/1000000; | |
result<<"\nFinally, in "<<cputime<<" time units, we explored " | |
<<nt<<" families of numbers for base "<<b; | |
if(chunkl!="")result<<" and the initial digit "<<chunkl; | |
if(chunkr!="")result<<" and the terminal digit "<<chunkr; | |
result<<"\nthere remains "<<nprime<<" primes to incorporate in the kernel, and " | |
<<nlong<<" families to analyse\n"; | |
} // end main |