A Prime Number Generator in Visual Basic

To generate a list of Fibonacci numbers, we created a generator class that emulates the behavior of the c# yield statement.  We’ll expand on this generator in another blog to enable us to write LINQ methods, but for right now we’ll use if for a similar task, generate a list or primes.

Problem 3

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

Writing the Solution First

It seems the easiest way to solve the Euler problems is to write the solution first, then write the functions that support this solution.  So here goes.

Dim result = 600851475143.PrimeFactors.Max

 

What I like about the above code is

·         How self explanatory it is. 

·         The clear path we now have for a solution.

An Extension Method for the Prime Factors of a Long

So let’s build the infrastructure that makes this code actually work.  The first thing we’ll need is an extension method to a long that returns all the prime factors for the number.

 

    <Runtime.CompilerServices.Extension()> _

    Function PrimeFactors(ByVal n As Long) As IEnumerable(Of Long)

        Return New Primes().TakeWhile(Function(p) p <= Math.Sqrt(n)).Where(Function(p) n Mod p = 0)

    End Function

 

Again, I love how declarative of intention this code is.  The Linq syntax really makes it easy to follow what the function is doing.  Let’s follow along.

 

·         New Primes() generates an as needed list of prime numbers. 

·         TakeWhile(Function(p) p <= Math.Sqrt(n)) keeps generating our primes until the prime is less than or equal to the square root of the number we’re finding the primes for.  The sieve of Eratosthenes lets us know this.

·         Where(Function(p) n Mod p = 0) checks if our number can be evenly divided by the prime.  If it can then of course it’s a prime factor

 

A Prime Number Generator

 

So the only thing we have left to look at is the Primes class that actually generates a list of primes.

 

Public Class Primes

    Inherits Generator(Of Long)

 

    Dim primes As New List(Of Long)

    Dim prime = 1

 

    Protected Overrides Function Generate() As Long

        Do While prime <= Long.MaxValue

            prime += 1

            If prime = 2 Then

                primes.Add(prime)

                Return prime

            End If

            Dim IsPrime = Function(n) primes.TakeWhile(Function(p) p <= Math.Sqrt(n)).FirstOrDefault(Function(p) n Mod p = 0) = 0

            If IsPrime(prime) Then

                primes.Add(prime)

                Return prime

            End If

        Loop

    End Function

End Class

 

Because we inherit from Generator, our Return statements behave the same as c# yield statements.  Every time we find a prime we add it to the list of primes.  The next time the Generate function is called the current number is checked against this list.  We really are following the steps from the Sieve of Eratosthenes.  Let’s break apart our IsPrime expression.

 

·      Dim IsPrime = Function(n) {expression} = 0 declares a function that takes a long and returns a Boolean. I’ve omitted the expression itself to make it easier to focus on the definition.

·      .TakeWhile(Function(p) p <= Math.Sqrt(n)) iterates our current list of primes until the prime is less than or equal to the square root of the number we’re testing.

·      FirstOrDefault(Function(p) n Mod p = 0) return the first prime factor or a 0 if there are no prime factors.

·      The expression is then checked against 0 to return a Boolean.

 

A Solution that Now Works

Now that we’ve built the infrastructure, our solution works when run.  Go ahead, try it out

 

Module Module1

 

    Sub Main()

        Dim result = 600851475143.PrimeFactors.Max

        Console.WriteLine(result)

        Console.ReadLine()

    End Sub

 

End Module

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>