
Perl solution to Event 6 in the 2008 Winter Scripting Games.
Solutions are also available for VBScript and Windows PowerShell.
By the time we did the Perl version of our prime numbers script, we’d started to get pretty good at figuring out how to calculate prime numbers. The net result? Our Perl script for determining the prime numbers between 1 and 200 turned out to be a little bit easier – and considerably shorter – than its VBScript and Windows PowerShell counterparts.
Here’s the script we came up with:
$arrPrimeNumbers[0] = 2;
$intPrimeNumbers = 1;
OuterLoop: for $intNumber (3 .. 200)
{
for $intDivisor (0 .. ($intPrimeNumbers-1))
{
if ($intNumber % $arrPrimeNumbers[$intDivisor] == 0)
{next OuterLoop;}
}
$arrPrimeNumbers[$intPrimeNumbers] = $intNumber;
$intPrimeNumbers++;
}
for $intValue (@arrPrimeNumbers)
{print "$intValue \n";}
By definition, the first prime number is 2 (1 is not considered a prime number). Consequently, the first thing we do is set up an array named @arrPrimeNumbers and assign the value 2 to the first item (item 0) in that array:
$arrPrimeNumbers[0] = 2;
Note. Yes, we know: we said the array was named @arrPrimeNumbers, yet we then use this syntax: $arrPrimeNumbers[0]. That’s because, in Perl, you use the $ to reference an individual item within an array, but use @ to reference the array itself. Crazy, but true! |
Once that’s done we use the following line of code to set up a for loop named OuterLoop, a loop designed to run from3 to 200 (that’s what that syntax 3 .. 200 means):
OuterLoop: for $intNumber (3 .. 200)
Inside the OuterLoop for loop we set up another loop, this one designed to run from 0 to the value of $intPrimeNumbers minus 1 ($intPrimeNumbers starts life off equal to 1). Inside this loop we’re going to use this line of code and the modulus operator (the % sign) to divide the value of $intNumber by the first item in the array $arrPrimeNumbers:
if ($intNumber % $arrPrimeNumbers[$intDivisor] == 0)
To be more specific, the first time through the loop we’re going to divide 3 (the value of $intNumber) by 2 (item 0 – that is, the first item – in the array $arrPrimeNumbers). We then use the modulus operator to check the remainder of dividing 3 by 2. If the remainder turns out to be 0 then we know that $intNumber is not a prime number; after all, by definition a prime number can only be evenly divided by 1 and itself. If the remainder is 0, we then use the next command to move to the next value in the loop OuterLoop:
if ($intNumber % $arrPrimeNumbers[$intDivisor] == 0)
As it turns out, 3 divided by 2 does not leave a remainder of 0. Therefore, we add the value 3 to the array $arrPrimeNumbers, then increment counter variable $intPrimeNumbers by 1. That’s what these two lines of code are for:
$arrPrimeNumbers[$intPrimeNumbers] = $intNumber; $intPrimeNumbers++;
And then it’s back to the top of the OuterLoop loop, where we repeat the process with the next number (4).
Note that by adding a new item to the array $arrPrimeNumbers we’re now changed the way our interior loop works. We’ll still divide each number by the first item in the array (2) and see if the remainder is 0. If it’s not, we’ll then divide that number by the second item in the loop (3); in other words, we’re going to divide each number by all the prime numbers that precede it. For example, when $intNumber is equal to 9 we’ll first divide 9 by 2. When that remainder fails to equal 0, we’ll then divide 9 by 3. When that remainder does equal 0 then we’ll know that 9 is not a prime number.
Etc.
All we have to do now is use the following block of code to echo back each of the values in the array @arrPrimeNumbers:
for $intValue (@arrPrimeNumbers)
{print "$intValue \n";}
If everything goes according to plan (which isn’t always the case when the Scripting Guys write Perl scripts) we should get back the following:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
Which is just exactly what we wanted to get back.