Bill Blogs in C#

Bill Wagner discusses C#, LINQ, and other items of interest

Euler Problem 7

Yes, it's true that I've been very lax in working on these problems.  It's been a combination of the day job, finishing all the editing tasks on "More Effective C#", and actually trying to keep the personal life intact.

The 7th problem is quite straightforward: find the 10,001st prime number. The main program is just two lines:

   1: static void Main(string[] args)
   2: {
   3:     var numbers = Common.Primes.GeneratePrimes().Skip(10000).First();
   4:  
   5:     Console.WriteLine(numbers);
   6: }

Simple LINQ stuff. The Skip() method skips the first N elements, and First() escapes the query and returns the first element.

Of course, the meat of the method is the GeneratePrimes() method:

   1: private static List<int> knownPrimes = new List<int>();
   2:  
   3: private static bool IsPrime(this int number)
   4: {
   5:     bool isPrime = knownPrimes.TrueForAll(n => number % n != 0);                   
   6:     if (isPrime)
   7:         knownPrimes.Add(number);
   8:     return isPrime;
   9: }
  10:  
  11: public static IEnumerable<int> GeneratePrimes()
  12: {
  13:     var range = Enumerable.Range(2, int.MaxValue-1);
  14:     var answers = from number in range
  15:                   where number.IsPrime()
  16:                   select number;
  17:  
  18:     return answers;
  19: }

GeneratePrimes() returns the sequence of primes. It uses the IsPrime() method to determine if a number is prime.  IsPrime() shows a couple of assumptions I've made to make this a reasonably simple method.  First of all, it assumes that all primes up to the number being examine have been found. Therefore, if the number has no prime factors smaller than itself, it must be a prime number. That saves quite a bit of work, because the set of primes smaller than N is much smaller than the set of numbers less than N.

To make this work, note that when a prime is found, it is added to the list of known primes.

Published Thu, Aug 14 2008 9:30 AM by wwagner

Comments

# re: Euler Problem 7@ Sunday, August 17, 2008 8:33 AM

Curiously, but not too surprisingly, your method is 5 times faster (approx) than one that attempts to minimize the number of primes checked by using the line:

           bool isPrime = knownPrimes.FindAll(n => (n * n) <= number).TrueForAll(n => number % n != 0);

in stead of the simpler version you used.

Clearly, testing whether the prime is less than or equal to the square root of the number being checked takes more work than just checking against all primes found so far! (approx 3 seconds for your version, in the IDE, vs 15 seconds for my version.)  Sometimes simpler is faster!

Best regards,

George Byrkit

by george byrkit

# re: Euler Problem 7@ Wednesday, August 20, 2008 4:52 PM

Any reason for using Skip(10000).First() instead of ElementAt(10001)?

(I'd also use a variable with a singular name rather than "numbers" when it's picking out a single number.)

Jon

# re: Euler Problem 7@ Sunday, August 24, 2008 8:00 AM

ElementAt ? --> NO !

Mentioned in text:

"First of all, it assumes that all primes up to the number being examine have been found."

by Pazu

# re: Euler Problem 7@ Sunday, August 24, 2008 4:36 PM

ElementAt(10001) would work just as well as Skip(10000).First().

The reason I ended up with the solution I did is simply that during testing, I would print out N prime for testing.  That made me see Skip and First rather than ElementAt().  (My test ran with Take(100), Take(1000), and Take(10000) just to verify some of the primes.

Both versions come up with the same answer, and take the same (measurable) amount of time

by wwagner

# Euler 10@ Wednesday, August 27, 2008 9:12 AM

After tackling number 9 yesterday , I thought I'd do #10 real quick since it seemend pretty easy. Calculate

# Euler 10@ Wednesday, August 27, 2008 9:24 AM

After tackling number 9 yesterday , I thought I&#39;d do #10 real quick since it seemend pretty easy

# Los problemas de Euler y LINQ@ Friday, August 29, 2008 8:22 AM

Revisando nuevos enlaces aparecidos durante agosto en la página de C# de MSDN, he dado con el blog de