ProjectEuler problem 35

Tiberiu Gal galtiberiu at gmail.com
Wed May 16 06:10:04 PDT 2012


The correct answer is 55
Your versions of isCircularPrime just truncates the number ( this 
is actually useful in a next problem though; )

prime_walks is a nice and efficient way to find primes ... and 
not a bit n00bfriendly.

I'm not posting it anywhere, I'm just learning and having fun.


On Wednesday, 16 May 2012 at 10:38:02 UTC, Era Scarecrow wrote:
> On Wednesday, 16 May 2012 at 09:46:06 UTC, Dmitry Olshansky 
> wrote:
>> On 16.05.2012 13:26, Tiberiu Gal wrote:
>
>>> foreach(i; 2 .. Max) {
>>> //writefln("is %s prime ? %s ", i, i.isPrime);
>>> if( i.isPrime && i.isCircularPrime) {
>>> cnt++;
>
>  Curiously i've just posted a sample (as part of another topic) 
> that progressively gives your larger primes. I haven't speed 
> tested it, but it always spits out primes.
>
> http://forum.dlang.org/thread/jovicg$jta$1@digitalmars.com
>
> So your code might look like...
>
> primes_walk pw;
> pw.cap = 1_000_000;
>
>  foreach(i; pw) {
>  if( i.isCircularPrime) { //i is always prime
>
>
>>> bool isCircularPrime( int n) {
>>>
>>> auto c = to!string(n);
>>> for(int i ; i < c.length; i++){
>>> c = c[1 .. $] ~ c[0];
>>
>> Don't ever do that. I mean allocating memory in tight cycle.
>> Instead use circular buffer.  (just use the same array and 
>> wrap indexes)
>
>  Hmm... I'd say this is totally written wrong... Rewriting it 
> to a more optimized one I got 15ms as a total running time for 
> 1_000_000 numbers. answer I got was 3181... remember I'm not 
> optimizing it or anything.
>
>  If this is a gem to show the power & speed of D, by all means 
> use it. But I want credit for my prime_walk...
>
> real    0m0.257s
> user    0m0.015s
> sys     0m0.015s
>
>
> -- rewrite with prime_walk
> module te35;
>
> import std.stdio;
>
> //prime_walk by Era Scarecrow.
> //range of primes, nearly O(1) for return.
> struct prime_walk {
>   int map[int];
>   int position = 2;
>   int cap = int.max;
>
>   int front() {
>     return position;
>   }
>
>   void popFront() {
>     //where the real work is done.
>
>     if ((position & 1) == 0) {
>       position++;
>     } else if (position>= cap) {
>       throw new Exception("Out of bounds!");
>     } else {
>       int div = position;
>       int p2 = position * 3;
>
>       //current spot IS a prime. So...
>       if (p2 < cap)
>         map[p2] = div;
>
>       position += 2;
>
>       //identify marked spot, if so we loop again.
>       while (position in map) {
>         div = map[position];
>         map.remove(position);
>         p2 = position;
>         do
>           p2 += div * 2;
>         while (p2 in map);
>
>         position += 2;
>         if (p2 <= cap)  //skip out, no need to save larger than 
> needed values.
>           map[p2] = div;
>       }
>     }
>   }
>
>   bool empty() {
>     return position >= cap;
>   }
> }
>
>
> const Max = 1_000_000;
>
> bool[Max] primes;
>
> void main() {
>   assert(bool.init == false);  //just a speedup if true. 
> removes 15ms
>   int cnt;
>   prime_walk pw;
>   pw.cap = Max; //no primes larger than 1Mil
>
>   foreach(i; pw) { //i is ALWAYS prime.
>     primes[i] = true;  //removes need for isprime totally if we 
> are never going above the foreach's i
>     if(i.isCircularPrime) {
>       cnt++;
> //      writefln("\t\tis %s, circular prime ", i); //already 
> confirmed
>     }
>   }
>
>   writeln(cnt);
>
> }
>
> //bool isPrime(int); //removed, not needed in this case
>
> //since it's always lower...
> //removes need for string, and only uses 1 division per level
> immutable int[] levels = [
> //1_000_000_000, 100_000_000, 10_000_000,  //completeness sake.
> 1_000_000, 100_000, 10_000, 1_000, 100, 10];
>
> bool isCircularPrime(int n) {
>
>   foreach(l; levels) {
>     if (l > n)
>       continue;
>
>     if (primes[n] == false)
>       return false;
>
>     n %= l; //remainder of 10, sorta...
>   }
>   return true;
> }




More information about the Digitalmars-d-learn mailing list