#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <time.h>
// code output at http://www.rankyouragent.com/primes/patn.c.output.txt
const char* INFINITE_ZEROS = "";
long AbsoluteValue(const long in)
{
if(in<0)
return in*(-1);
return in;
}
long FindFirstZero(const char* bitString )
{
long firstZero = 1;
long bitStringLength = strlen(bitString);
long i=0;
for (i = 0; i < bitStringLength; i++ )
if ( bitString[i]=='0' ) return i + 1;
return firstZero;
}
char* Elemental(long firstZero )
{
long elementalSize = (2*firstZero) + 1;
char* elemental = (char*) malloc(elementalSize+1);
long i=0;
for ( i = 0; i < elementalSize; i++ )
if ( i == 0 )
elemental[i] = '1';
else
elemental[i] = '0';
elemental[elementalSize]='\0';
return elemental;
}
const char* Merge(const char* lhsPattern, const char* rhsPattern ) {
// Note 0... MERGE anyPattern = anyPattern
long firstZeroLhsPattern = FindFirstZero( lhsPattern );
long mergedPatternLength = strlen(lhsPattern) * strlen(rhsPattern);
long lhsPatternLength = strlen(lhsPattern);
long rhsPatternLength = strlen(rhsPattern);
char* mergedPattern = (char*) malloc(mergedPatternLength+1);
long i=0;
time_t start=0,finish=0;
start = time(NULL);
if ( lhsPattern == INFINITE_ZEROS ) return rhsPattern;
for ( i = 0; i < mergedPatternLength; i++ ) {
char currLhsBit = '0';
char currRhsBit = '0';
currLhsBit = lhsPattern[i % ( lhsPatternLength )];
// rhs pattern is shifted to align with first zero in LHS pattern
currRhsBit = rhsPattern[AbsoluteValue( ( i + 1 - firstZeroLhsPattern ) ) % rhsPatternLength];
// or the result to produce the merged pattern
mergedPattern[i] = currLhsBit=='1' || currRhsBit=='1' ? '1':'0';
}
mergedPattern[mergedPatternLength]='\0';
finish = time(NULL);
//printf("Merge took %li seconds\n",finish-start);
return mergedPattern;
}
const char* currElemental = NULL;
const char* Pat(const long n)
{
if(n==0)
return INFINITE_ZEROS;
else
{
const char* PatNMinusOne = Pat(n-1);
long firstZeroLhsPattern = FindFirstZero(PatNMinusOne);
char* elemental = Elemental(firstZeroLhsPattern);
currElemental = elemental;
const char * toReturn = Merge(PatNMinusOne,elemental);
return toReturn;
}
}
// a cache to speed things along
// initialize to -1
#define PRIME_CACHE_SIZE 200000
char primeCache[PRIME_CACHE_SIZE];
// a basic implementation of isPrime
char isPrime( long n )
{
//check cache first
if(n<PRIME_CACHE_SIZE)
{
char cacheValue = primeCache[n];
if(cacheValue>0)
return cacheValue;
}
char prime = 1;
long i=3;
for (i = 3; i <= lround(sqrt((double)n)); i += 2 )
if ( n % i == 0 ) {
prime = 0;
break;
}
if ( ( n % 2 != 0 && prime && n > 2 ) || n == 2 ) {
primeCache[n]=1;
return true;
}
else {
primeCache[n]=0;
return false;
}
}
// return curr prime note I consider P(1) = 3
long P( int n )
{
long i=0;
long currPrime = 0;
for ( i = 3; i < INT_MAX ; i += 2 ) {
if ( isPrime( i ) )
currPrime++;
if ( currPrime == n ) return i;
}
return 1;
}
// returns the number of zeros in Pat(f(n),n)
long zeros( int n )
{
if ( n == 1 ) return 2;
return zeros( n - 1 ) * ( P( n ) - 1 );
}
long twins( int n )
{
if ( n == 1 ) return 1;
return twins( n - 1 ) * ( P( n ) - 2 );
}
long triplets( int n )
{
if ( n == 2 ) return 2;
return triplets( n - 1 ) * ( P( n ) - 3 );
}
long quadruplets( int n )
{
if ( n == 2 ) return 1;
return quadruplets( n - 1 ) * ( P( n ) - 4 );
}
// returns the number of ones in Pat(f(n),n)
long ones( int n )
{
if ( n == 1 ) return 1;
return ( ones( n - 1 ) * P( n ) ) + zeros( n - 1 );
}
// #P[P(n)->P(n)^2] = [zeros(n-1) * (P(n)^2 - P(n))] / P(n-1)#
// #P_Corrected[P(n)->P(n)^2] = {[zeros(n-1) * (P(n)^2 - P(n))] / P(n-1)#} + 2 ^ (#P[P(n)->P(n)^2] / 100)
// this is the number of primes between P(n) and P(n)^2
long numberPrimesBetweenPnAndPnSquared(int n, char addCorrection)
{
if(n<2)
return -1; //error
long Pn = P(n);
long PnSquared = Pn*Pn;
int primorialIndex = n-1;
double result = ((double)(zeros(n-1) * (PnSquared-Pn)));
// divide through by the primorial(n-1)
while(primorialIndex>0)
{
result /=P(primorialIndex);
primorialIndex--;
}
// my P(n) function omits 2 so we'll add it back into the primorial here
result /= 2;
if(addCorrection)
{
double nDouble = (double)n;
double correction = log(nDouble)*0.145348;
nDouble *= correction;
double nDoubleSquared = nDouble*nDouble;
long nDoubleSquaredLong = lround(nDoubleSquared);
result -= nDoubleSquaredLong;
}
return lround(result);
}
long numPrimePnMinusOneSquaredToPnSquared(int n)
{
if(n<2)
return -1; //error
long Pn = P(n);
long PnSquared = Pn*Pn;
long PnMinusOne = P(n-1);
long PnMinusOneSquared = PnMinusOne * PnMinusOne;
long numPrime = 0;
for (long i=PnMinusOneSquared+2; i<PnSquared; i+=2)
if(isPrime(i))
numPrime++;
return numPrime;
}
long numberPrimesBetweenPnMinusOneSquaredAndPnSquared(int n, char correct)
{
if(n<2)
return -1; //error
long Pn = P(n);
long PnSquared = Pn*Pn;
long PnMinusOne = P(n-1);
long PnMinusOneSquared = PnMinusOne * PnMinusOne;
int primorialIndex = n;
double result = ((double)(zeros(n) * (PnSquared-PnMinusOneSquared)));
// divide through by the primorial(n-1)
while(primorialIndex>0)
{
result /=P(primorialIndex);
primorialIndex--;
}
// my P(n) function omits 2 so we'll add it back into the primorial here
result /= 2;
if(correct)
{
double nDouble = (double)n;
double correction = log(nDouble)*0.145348;
nDouble *= correction;
double nDoubleSquared = nDouble*nDouble;
long nDoubleSquaredLong = lround(nDoubleSquared);
result -= nDoubleSquaredLong;
}
return lround(result);
}
long numberTwinsBetweenPnAndPnSquared(int n, char addCorrection)
{
if(n<2)
return -1; //error
long Pn = P(n);
long PnSquared = Pn*Pn;
int primorialIndex = n-1;
double result = ((double)(twins(n-1) * (PnSquared-Pn)));
// divide through by the primorial(n-1)
while(primorialIndex>0)
{
result /=P(primorialIndex);
primorialIndex--;
}
// my P(n) function omits 2 so we'll add it back into the primorial here
result /= 2;
if(addCorrection)
{
double nDouble = (double)n;
double correction = log(nDouble)*0.058652;
nDouble *= correction;
double nDoubleSquared = nDouble*nDouble;
long nDoubleSquaredLong = lround(nDoubleSquared);
result -= nDoubleSquaredLong;
}
return lround(result);
}
long numberTripletsBetweenPnAndPnSquared(int n, char addCorrection)
{
if(n<3)
return -1; //error
long Pn = P(n);
long PnSquared = Pn*Pn;
int primorialIndex = n-1;
double result = ((double)(triplets(n-1) * (PnSquared-Pn)));
// divide through by the primorial(n-1)
while(primorialIndex>0)
{
result /=P(primorialIndex);
primorialIndex--;
}
// my P(n) function omits 2 so we'll add it back into the primorial here
result /= 2;
if(addCorrection)
{
double nDouble = (double)n;
double correction = log(nDouble)*0.02881;
nDouble *= correction;
double nDoubleSquared = nDouble*nDouble;
long nDoubleSquaredLong = lround(nDoubleSquared);
result -= nDoubleSquaredLong;
}
return lround(result);
}
long numberQuadrupletsBetweenPnAndPnSquared(int n, char addCorrection)
{
if(n<3)
return -1; //error
long Pn = P(n);
long PnSquared = Pn*Pn;
int primorialIndex = n-1;
double result = ((double)(quadruplets(n-1) * (PnSquared-Pn)));
// divide through by the primorial(n-1)
while(primorialIndex>0)
{
result /=P(primorialIndex);
primorialIndex--;
}
// my P(n) function omits 2 so we'll add it back into the primorial here
result /= 2;
if(addCorrection)
{
double nDouble = (double)n;
double correction = log(nDouble)*0.00718;
nDouble *= correction;
double nDoubleSquared = nDouble*nDouble;
long nDoubleSquaredLong = lround(nDoubleSquared);
result -= nDoubleSquaredLong;
}
return lround(result);
}
int main()
{
time_t start=0,finish=0;
long i=0,x=0;
const char* patnDisplay = NULL;
const char* patn = NULL;
long calculatedOnes=0,calculatedZeros=0;
start = time(NULL);
// initialize primeCache to all -1;
for(i=0;i<PRIME_CACHE_SIZE;i++)
primeCache[i]=-1;
// demonstrate Pat(n)
for(i=0; i<8; i++)
{
long n = i+1;
long lenPatn=0;
long numOnes=0,numZeros=0,singletonCandidates=0,twinCandidates=0,totalCandidates=0;
int x=0;
numOnes=0; numZeros=0;singletonCandidates=0;twinCandidates=0,totalCandidates=0;
patn = Pat(n);
lenPatn = strlen(patn);
for(x=0;x<lenPatn;x++)
{
if(patn[x]=='1')
numOnes++;
else
numZeros++;
//singleton candidates
if ( ( patn[x]=='0' ) && ( patn[x - 1]=='1' ) && ( patn[(x + 1) % lenPatn]=='1' ) ) singletonCandidates++;
//twin candidates
if ( ( patn[x]=='0' ) && ( patn[x - 1]=='0' ) ) twinCandidates++;
}
patnDisplay = patn;
if(i>4)
patnDisplay = "TOO BIG!";
printf( "---------------------------------------------------------\n" );
int elementalShiftedLength = strlen(currElemental)+1;
char* elementalShifted = (char*)malloc(elementalShiftedLength);
int f0 =(int)(P((int)n)-1)/2;
for(int s=0;s<elementalShiftedLength-1;s++)
{
if(s+1==f0)
elementalShifted[s]='1';
else
elementalShifted[s]='0';
}
elementalShifted[elementalShiftedLength-1]='\0'; // null terminate
printf("Elemental(2f0+1,f0=%i) = %s -- shifted to align with f0 --> %s\n",f0,currElemental,elementalShifted);
printf("Pat(2n+1,n=%i) = %s\n",n,patnDisplay);
printf("Size = %li\n",lenPatn);
printf("Number of 1's = %li; %li/%li = %Lf \n",numOnes,numOnes,lenPatn,(double)numOnes/(double)lenPatn);
printf("Number of 0's = %li; %li/%li = %Lf \n",numZeros,numZeros,lenPatn,(double)numZeros/(double)lenPatn);
totalCandidates = singletonCandidates+twinCandidates;
printf("Total Candidates= %li\n",totalCandidates);
printf("Singleton Candidates = %li; %li/%li = %Lf \n",singletonCandidates,singletonCandidates, singletonCandidates+twinCandidates,(double)singletonCandidates/(double)totalCandidates);
printf("Twin Candidates = %li; %li/%li = %Lf \n",twinCandidates,twinCandidates, singletonCandidates+twinCandidates,(double)twinCandidates/(double)totalCandidates);
printf( "---------------------------------------------------------\n" );
free((void*)patn);
free((void*)currElemental);
free((void*)elementalShifted);
}// for
// examine the ones(n) and zeros(n) functions
printf("%s","IT IS ALSO POSSIBLE TO ALGORITHMICALLY DETERMINE THE # OF ONES AND ZEROS AS OUTLINED ON MY WEBSITE.\n" );
for ( x = 2; x < 9 ; x++ ) {
calculatedOnes = ones( x );
calculatedZeros = zeros( x );
printf( "n=%li; Ones->%li Zeros->%li zeros/(ones+zeros) = %Lf\n",x,calculatedOnes,calculatedZeros,((double)calculatedZeros )/(double)( calculatedOnes + calculatedZeros ) );
}
printf( "%s", "---------------------------------------------------------\n" );
// compare with actual values of primes:oddNumbers between P(n) and P(n)^2
// System.out.println("Long.MAX_VALUE="+Long.MAX_VALUE);
printf( "COMPARE THE ABOVE VALUES TO THE NUMBER OF PRIMES/ODD BETWEEN P(n)->P(n)^2\n" );
printf( "NOTE: P(n)->P(n)^2 compares to n-1 above because (Pat(n-1)) is in effect between P(n)->P(n)^2)\n" );
// an array to store n->numPrime for comparison later with #P[P(n)->P(n)^2]
#define ITERATIONS 80
long nToNumPrime[ITERATIONS+1];
long nToNumTwin[ITERATIONS+1];
long nToNumTrip[ITERATIONS+1];
long nToNumQuad[ITERATIONS+1];
for ( x = 1; x < ITERATIONS; x++ ) {
long thisPrime = P( x );
long thisPrimeSquared = thisPrime * thisPrime;
long numPrime, numOdd, numTwin, numTrip,numQuad;
numPrime = 0;
numTwin = 0;
numOdd = 0;
numTrip=0;
numQuad=0;
for ( long j = thisPrime + 2; j < thisPrimeSquared; j += 2 ) {
if ( isPrime( j ) ) numPrime++;
if ( isPrime( j ) && isPrime(j-2) && (j>3) ) numTwin++;
if ( isPrime( j ) && isPrime(j-4) && isPrime(j-6) && (j>5) ) numTrip++;
if ( isPrime( j ) && isPrime(j-2) && isPrime(j-6) && isPrime(j-8) && (j>9) ) numQuad++;
numOdd++;
}
nToNumPrime[x]=numPrime;
nToNumTwin[x]=numTwin;
nToNumTrip[x]=numTrip;
nToNumQuad[x]=numQuad;
printf( "P(%li)->P(%li)^2 : %li->%li numPrime/numOdd = %li/%li = %Lf\n",x,x,thisPrime,thisPrimeSquared,numPrime,numOdd,((double)numPrime/(double)numOdd) );
}
// examining the #P[P(n)->P(n)^2] formula
printf( "---------------------------------------------------------\n" );
printf( "EXAMINING THE #P[P(n)->P(n)^2] AND #P_Corrected[P(n)->P(n)^2] FORMULAE\n" );
// anything more than 9 overflows double
for ( x = 2; x < 9; x++ ) {
printf( "#P[P(%li)->P(%li)^2] = %li; #P_Corrected[P(%li)->P(%li)^2] = %li; actual number primes in this interval = %li\n",x,x,numberPrimesBetweenPnAndPnSquared(x,0),x,x,numberPrimesBetweenPnAndPnSquared(x,1),nToNumPrime[x]);
}
// examining the #P[P(n-1)^2->P(n)^2] formula
printf( "---------------------------------------------------------\n" );
printf( "EXAMINING THE #P[P(n-1)^2->P(n)^2] AND #P_Corrected[P(n-1)^2->P(n)^2] FORMULAE\n" );
// anything more than 8 overflows double
for ( x = 2; x < 8; x++ ) {
printf( "#P[P(%li)^2->P(%li)^2] = %li; #P_Corrected[P(%li)^2->P(%li)^2] = %li; actual number primes in this interval = %li\n",x-1,x,numberPrimesBetweenPnMinusOneSquaredAndPnSquared(x,0),x-1,x,numberPrimesBetweenPnMinusOneSquaredAndPnSquared(x,1),numPrimePnMinusOneSquaredToPnSquared(x));
}
// examining the #Twins[P(n)->P(n)^2] formula
printf( "---------------------------------------------------------\n" );
printf( "EXAMINING THE #Twins[P(n)->P(n)^2] AND #Twins_Corrected[P(n)->P(n)^2] FORMULAE\n" );
// anything more than 9 overflows double
for ( x = 2; x < 9; x++ ) {
printf( "#Twins[P(%li)->P(%li)^2] = %li; #Twins_Corrected[P(%li)->P(%li)^2] = %li; actual number twins in this interval = %li\n",x,x,numberTwinsBetweenPnAndPnSquared(x,0),x,x,numberTwinsBetweenPnAndPnSquared(x,1),nToNumTwin[x]);
}
// examining the #Triplets[P(n)->P(n)^2] formula
printf( "---------------------------------------------------------\n" );
printf( "EXAMINING THE #Triplets[P(n)->P(n)^2] AND #Triplets_Corrected[P(n)->P(n)^2] FORMULAE\n" );
// anything more than 9 overflows double
for ( x = 3; x < 9; x++ ) {
printf( "#Triplets[P(%li)->P(%li)^2] = %li; #Triplets_Corrected[P(%li)->P(%li)^2] = %li; actual number triplets in this interval = %li\n",x,x,numberTripletsBetweenPnAndPnSquared(x,0),x,x,numberTripletsBetweenPnAndPnSquared(x,1),nToNumTrip[x]);
}
// examining the #Quadruplets[P(n)->P(n)^2] formula
printf( "---------------------------------------------------------\n" );
printf( "EXAMINING THE #Quadruplets[P(n)->P(n)^2] AND #Quadruplets_Corrected[P(n)->P(n)^2] FORMULAE\n" );
// anything more than 9 overflows double
for ( x = 3; x < 9; x++ ) {
printf( "#Quadruplets[P(%li)->P(%li)^2] = %li; #Quadruplets_Corrected[P(%li)->P(%li)^2] = %li; actual number quadruplets in this interval = %li\n",x,x,numberQuadrupletsBetweenPnAndPnSquared(x,0),x,x,numberQuadrupletsBetweenPnAndPnSquared(x,1),nToNumQuad[x]);
}
finish = time(NULL);
printf( "---------------------------------------------------------\n" );
printf("Execution time = %li seconds.",finish-start);
return 0;
}