public static void Main(string [] args)
    {
        IPrimeGenerator pg;
        // pg = new PrimeGenerator();

        // FIXME: this is a hack since we iterate to the
        // first prime ABOVE 2000000.
        pg = new SieveGenerator(2010000);

        pg.Init();

        UInt32 current = pg.Next();
        UInt64 sum = 0;
        int count = 1;

        for (; current < 2000000 ; current = pg.Next(), count++)
        {
          if (UInt64.MaxValue - sum < current)
        throw new Exception("OVERFLOW");

          sum += current;

          if (count % 100 == 0)
        Console.WriteLine("{0}:{1}...", count, current);
        }

        Console.WriteLine("Result: {0}", sum);
    }
    public static void Main(string[] args)
    {
        //    IPrimeGenerator generator = new BruteForceGenerator();

        // FIXME: Hack. 1010000 used to ensure that we get a prime above
        // 1000000.
        IPrimeGenerator generator = new SieveGenerator(1010000);
        generator.Init();

        UInt32 p = generator.Next();

        // FIXME: checking existence in this hashset takes way too long...
        HashSet<UInt32> circularPrimes = new HashSet<UInt32>();

        while(p <= 1e6)
        {
          // Console.WriteLine("Trying {0}", p);

          List<UInt32> rotations = findRotations(p);

          if ((p == 2 || rotations.All(i => i % 2 != 0)) && // filter even except for two
          rotations.All(target => generator.IsPrime(target)) &&
          !circularPrimes.Contains(p))
          {
        circularPrimes.UnionWith(rotations);
        Console.WriteLine("circular set: [{0}]", String.Join(", ", rotations.Select(i => i.ToString()).ToArray()));
          }

          p = generator.Next();
        }

        Console.WriteLine("Result: {0}", circularPrimes.Count);
    }