Sieve of Eratosthenes - Try 4 - DSL





2
Date Submitted Sun. Apr. 29th, 2007 10:07 PM
Revision 1 of 1
Helper esumerfd
Tags "Sieve | Eratosthenes" | groovy | of | primes
Comments 0 comments
Generate prime numbers below some limit. This snippet incorporates some DSL like keywords to describe the prime algorithm.
package simulation.sieve.try5;

/*
 * Super DSLize the algorithm.
 * 1) Convert all algorithm constructs into domain words
 */

class Sieve5
{
    def eratosthenes(a_limit)
    {
        def primes
       
        use (IntegerCategory,ListCategory)
        {
            primes = a_limit.seive() {
               
                ifANumberHasAFactor
                {
                    thisIsNotAPrime()
                }
                elseIfTheNumberIsTheSameAsTheFactor
                {
                    thisIsAPrime()
                }
            }
        }

        primes
    }
}

/*
* Add prime related methods to Integer.
*/

class IntegerCategory
{
    def static seive(Integer a_limit, Closure a_closure)
    {
        def possiblePrimes = a_limit.toList()
       
        def grammar = PrimeGrammar.newInstance()
        grammar.findPrimes(possiblePrimes, a_closure)
    }

    /*
     * Generate a list of numbers with this value as the upper bound
     */

    def static toList(Integer a_limit)
    {
        def list = []

        a_limit.times { number ->
            list << number
        }

        list
    }

    /*
     * Determine if this number is divisible by the factor. If eliminate
     * the number if it is  less than the factor or zero then it can not
     * be prime. Then check for prime by not equal self and not divisible
     * by factor.
     */

    def static hasPrimeFactor(Integer a_number, Integer a_factor)
    {
         (a_number > a_factor
            && a_number.value != 0
              && a_number != a_factor
              && a_number % a_factor == 0)
    }
}

class ListCategory
{
    def static eachFactor(ArrayList a_list, Closure a_closure)
    {
        (2..a_list.size()).each a_closure
    }

    def static eachPossiblePrime(ArrayList a_list, Closure a_closure)
    {
        def removals = []

        a_list.each { number ->

            // Since this method is in a list now perhaps we should
            // not filter out other types in the list
            if (number instanceof Integer)
            {
                a_closure(number)
            }
        }

        /*
         * This is a little ugly. A nasty dependency between the
         * grammar and this list injected method.
         */

        def grammar = a_closure.delegate
        grammar.eachRemoval { removal ->
            a_list.remove((Object)removal)
        }
    }
}

class PrimeGrammar
{
    def primes = []
   
    def currentFactor
    def currentNumber

    def removals = []
   
    def findPrimes(a_possiblePrimes, a_closure)
    {
        a_closure.delegate = this

        a_possiblePrimes.eachFactor { factor ->

            a_possiblePrimes.eachPossiblePrime() { number ->

                currentFactor = factor
                currentNumber = number

                a_closure()
            }
        }
       
        primes
    }
   
    def ifANumberHasAFactor(a_closure)
    {
        if (currentNumber.hasPrimeFactor(currentFactor))
        {
            a_closure()
        }
    }
   
    def elseIfTheNumberIsTheSameAsTheFactor(a_closure)
    {
        if (!currentNumber.hasPrimeFactor(currentFactor)
            && currentNumber == currentFactor)
        {
            a_closure()
        }
    }

    def thisIsNotAPrime()
    {
        removals << currentNumber
    }
   
    def thisIsAPrime(a_closure)
    {
        primes << currentFactor
    }
   
    def eachRemoval(a_closure)
    {
        removals.each { removal ->
            a_closure(removal)
        }
    }
}

...

 

Edward Sumerfield

Comments

There are currently no comments for this snippet.

Voting

Votes Down


Helper morad