Project Euler Homework

035.cpp

00001 #include <iostream>
00002 using namespace std;
00003 
00004 const unsigned MAX = 1000000;
00005 class prime_table
00006 {
00007         bool x[MAX];
00008 public:
00009         prime_table();
00010         bool has(unsigned k);
00011         unsigned next(unsigned n);
00012 };
00013 
00014 prime_table::prime_table()
00015 {
00016         //assume all except 0,1 are prime
00017         x[0]=x[1]=0;
00018         for (bool* p=x+2;p-x<MAX;p++)*p=1;
00019 
00020         for (unsigned n = 2; n < MAX;n = next(n)) {
00021                 unsigned idx=n+n;
00022                 while (idx < MAX) {
00023                         x[idx]=0;
00024                         idx+=n;
00025                 }
00026         }
00027 }
00028 
00029 unsigned prime_table::next(unsigned n)
00030 {
00031         if (n>=MAX)return MAX;
00032         bool* p = x+n;
00033         do {
00034                 p++;
00035                 if (*p)return (p-x);
00036         } while (p-x < MAX);
00037         return MAX;
00038 }
00039 
00040 bool prime_table::has(unsigned k)
00041 {
00042         if (k>=MAX) {
00043                 cerr << "Error: overflow";
00044                 return 0;
00045         }
00046         return x[k];
00047 }
00048 
00049 unsigned pow10(unsigned p)
00050 {
00051         unsigned prod=1;
00052         for (unsigned i=1;i<=p;i++)
00053                 prod*=10;
00054         return prod;
00055 }
00056 
00057 unsigned num_length(unsigned x)
00058 {
00059         unsigned len=0;
00060         for (;x>0;x/=10)
00061                 len++;
00062         return len;
00063 }
00064 
00065 inline unsigned circulate(unsigned y,unsigned len)
00066 {
00067         return y/10+(y%10)*pow10(len-1);        //shift the right-most digit to left
00068 }
00069 
00070 class lookup_table
00071 {
00072         bool x[MAX];
00073 public:
00074         lookup_table() {
00075                 for (unsigned i=0;i<MAX;i++)
00076                         x[i]=0;
00077         }
00078         void mark(unsigned k) {
00079                 x[k]=1;
00080         }
00081         unsigned count() {
00082                 unsigned cnt=0;
00083                 for (unsigned i=0;i<MAX;i++)
00084                         if (x[i])
00085                                 cnt++;
00086                 return cnt;
00087         }
00088         bool has(unsigned k) {
00089                 if (k>=MAX) {
00090                         cerr << "Error: overflow";
00091                         return 0;
00092                 }
00093                 return x[k];
00094         }
00095 };
00096 
00097 
00098 
00099 int main()
00100 {
00101         prime_table primes;
00102         lookup_table circular_primes;
00103 
00104         unsigned count=0;
00105         for (unsigned p=2;p<MAX;p=primes.next(p)) {
00106                 //if p is already a circular prime, skip it
00107                 if (circular_primes.has(p))continue;
00108 
00109                 //check if p is circular
00110                 unsigned len=num_length(p);
00111                 unsigned y=p;
00112                 bool flag=1;
00113                 for (unsigned count=1;count<=len;count++) {
00114                         y = circulate(y,len);
00115                         if (!primes.has(y)) {
00116                                 flag=0;
00117                                 break;
00118                         }
00119                 }
00120                 //record all circular primes
00121                 if (flag)
00122                         for (unsigned count=1;count<=len;count++) {
00123                                 y = circulate(y,len);
00124                                 circular_primes.mark(y);
00125                                 //cout << y << '\t';
00126                         }
00127         }
00128         cout << circular_primes.count() << endl;
00129         return 0;
00130 }
 All Classes Files Functions Variables