Prime Number Program in Deluge

Prime Number Program in Deluge

Introduction

Prime numbers have fascinated mathematicians for thousands of years, and they still show up all the time in programming — from encryption algorithms to random number generation. But before we get into any of that, let us start with something much more practical: how do you actually check whether a number is prime inside a Zoho Deluge script?

In this post I will cover the concept from scratch, walk through the special edge cases that catch people out, and then show you two different Deluge implementations — a straightforward brute-force approach and an optimised version that does far less work. By the end you will understand not just the code but the reasoning behind it.


What Makes a Number Prime?

A prime number is a natural number greater than 1 that has exactly two factors: 1 and itself. That is the whole definition. No middle ground, no exceptions.

What that really means in practice: if you try to divide a prime by any number other than 1 or itself, you will always get a remainder. There is nothing that divides it cleanly.

Examples of prime numbers:

2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37...

And here are some composite (not prime) numbers, with their factors listed out so you can see why they do not qualify:

Number Factors Why Not Prime
4 1, 2, 4 Divisible by 2
6 1, 2, 3, 6 Divisible by 2 and 3
9 1, 3, 9 Divisible by 3

Two Special Cases Worth Memorising

These two come up constantly and they are worth having locked in before you write any code.

1
1 is NOT a prime number. It only has one factor — itself. Primes need exactly two distinct factors, so 1 is excluded by definition. A lot of beginners assume 1 qualifies; it does not.
2
2 is the only even prime number. Every other even number is divisible by 2, which means it has at least three factors: 1, 2, and itself. But 2 itself has only 1 and 2 as factors, so it qualifies. This makes 2 genuinely unique among primes.

Both of these cases need to be handled explicitly in your code, which you will see reflected in both methods below.


How Do You Actually Check for Primality?

The core idea is straightforward: try to divide your number by every integer from 2 up to some limit. If any of them divide evenly (remainder zero), the number is composite. If none of them do, it is prime.

The interesting question is: what is the limit? Do you really need to test every number all the way up to n - 1? That is what Method 1 does. Method 2 uses a smarter stopping point that cuts the work down significantly. We will look at both.

One Deluge-specific thing to flag before the code: Deluge does not have a traditional counting loop like for i = 2 to n. Instead, we generate a dummy list with a set number of entries and use for each to iterate through it, maintaining a manual counter. It is a well-known Deluge pattern once you have seen it a couple of times.


Method 1: Brute Force Check (Division from 2 to n−1)

This is the most direct translation of the definition into code. We check every integer from 2 all the way up to number - 1. If any of them divides the number without a remainder, we flag it as not prime and stop early.

number = 29;
isPrime = true;

// Anything less than or equal to 1 is immediately not prime
if(number <= 1)
{
    isPrime = false;
}
else
{
    // Build a dummy list with (number - 2) entries
    // This lets us loop from counter = 2 up to number - 1
    listLength = number - 1;
    loopList = "".leftPad(listLength - 1).toList("");

    counter = 2;
    for each dummy in loopList
    {
        // If number divides evenly by counter, it is not prime
        if(number % counter == 0)
        {
            isPrime = false;
            break;
        }
        counter = counter + 1;
    }
}

info (number + " is prime? " + isPrime);
// Output: 29 is prime? true

Breaking Down the Key Parts

The leftPad trick for generating a loop

"".leftPad(n) creates a string padded to length n with spaces. Calling toList("") on it splits that string character by character, giving us a list with exactly n items. We do not care what is in the list — we only care about its length, which controls how many times the loop runs. The actual iteration tracking is done with the manual counter variable.

The modulo operator %

number % counter gives you the remainder after dividing number by counter. If that remainder is zero, it means counter divides number perfectly — which means number has a factor other than 1 and itself, so it cannot be prime. We set isPrime = false and break out of the loop immediately rather than wasting time checking more divisors.

Why check up to number - 1?

Because we want to test every possible divisor between 2 and one less than the number itself. If none of them divide it evenly, the number has no factors other than 1 and itself — which is exactly the definition of prime. This is correct but not the most efficient approach, especially for large numbers. That is where Method 2 comes in.


Method 2: Optimised Check Using the Square Root

Here is something that a lot of people do not immediately see: if a number n has a factor larger than its square root, then it must also have a corresponding factor smaller than its square root. Factors come in pairs.

Take 36 as an example. Its factor pairs are: 1×36, 2×18, 3×12, 4×9, 6×6. The square root of 36 is 6. Notice how every factor above 6 is already paired with a factor below 6. So once you have checked all divisors up to the square root, you have already caught everything.

For a number like 29, the square root is roughly 5.38. So instead of testing 2, 3, 4, 5, 6, 7, 8... all the way to 28, we only need to test 2, 3, 4, 5. That is a massive saving for larger numbers, and it compounds quickly.

number = 29;
isPrime = true;

if(number <= 1)
{
    isPrime = false;
}
else
{
    // Find the square root of the number and round it down to a whole number
    // We only need to test divisors up to this limit
    limit = (sqrt(number)).toLong();

    // Build a loop list of length (limit - 1) so our counter runs 2, 3, ..., limit
    loopLen = limit - 1;
    loopList = "".leftPad(loopLen - 1).toList("");

    counter = 2;
    for each dummy in loopList
    {
        if(number % counter == 0)
        {
            isPrime = false;
            break;
        }
        counter = counter + 1;
    }
}

info number + " prime? " + isPrime;
// Output: 29 prime? true

What sqrt(number).toLong() does

sqrt() in Deluge returns a decimal value. For 29, that is approximately 5.385. Calling .toLong() truncates it to 5. This floors the result, which is exactly what we want — we need to check every whole number up to and including the floor of the square root. So our loop runs through divisors 2, 3, 4, 5 and then stops.


Method 1 vs Method 2 — How Do They Compare?

To make the difference concrete, here is how many divisor checks each method performs for a few different inputs:

Number Method 1 checks (up to n−1) Method 2 checks (up to √n)
29 27 checks 4 checks
97 95 checks 8 checks
997 995 checks 30 checks

The bigger the number, the more dramatic the difference. For small numbers in a quick test, Method 1 is perfectly fine. For anything inside a loop that runs many times, or for checking larger numbers, Method 2 is the right choice.

Method 1 Method 2
Checks up to n − 1 √n (floor)
Speed Slower for large n Much faster
Accuracy Correct Correct
Complexity Slightly simpler to read One extra step (sqrt + toLong)
Best for Learning, small numbers Production scripts, large numbers

Tracing Method 2 for the Number 29

Let us step through Method 2 with number = 29 so you can see exactly what happens on each loop pass:

Setup: sqrt(29) ≈ 5.385limit = 5, so the loop runs 4 times (counter goes 2, 3, 4, 5)
Pass counter 29 % counter isPrime
1 2 1 (not zero) still true
2 3 2 (not zero) still true
3 4 1 (not zero) still true
4 5 4 (not zero) true ✔

No divisor produced a remainder of zero, so 29 is confirmed prime. The loop only ran 4 times instead of 27. That is the square root optimisation doing its job.


Quick Test Cases to Try

Swap in these values for number and check the output yourself in Zoho's function editor:

Input Expected Output Reason
1 false 1 is not prime by definition
2 true Only even prime number
9 false Divisible by 3
29 true No divisors between 2 and 5
49 false 7 × 7 = 49
97 true Prime — no divisors up to √97 ≈ 9

49 is a good one to include because it looks prime at first glance — it is an odd number and does not end in 0 or 5. But 7 × 7 catches it, which is exactly why the square root check matters. Without it, you might miss that edge case in a quick mental test.


Common Mistakes and How to Avoid Them

Forgetting to handle n ≤ 1

Both methods start with an explicit check for number <= 1. Skip this and you will get incorrect results for 0, 1, or negative inputs. Always guard the entry point.

Getting the loop length wrong in Method 2

The list length needs to produce exactly limit - 1 iterations (for counter values 2 through limit). Off-by-one errors here are easy to introduce. Add an info counter; inside the loop when testing to confirm your counter runs the right sequence.

Not calling toLong() on the square root

sqrt() returns a decimal. If you try to use it directly as a list length, Deluge will throw a type error. Always call .toLong() to convert it to a whole number first.


Wrapping Up

Checking for prime numbers is one of those problems that teaches you several important scripting habits at once — guarding edge cases, choosing the right stopping point for a loop, using the modulo operator, and understanding why algorithmic efficiency actually matters even in a language like Deluge.

If you are just starting out with Deluge, Method 1 is worth understanding first because the logic maps directly to the definition of primality. Once that clicks, move to Method 2 and really think through the square root reasoning — it is one of those ideas that feels surprising the first time and then obvious every time after.

A good next exercise: modify Method 2 to print every prime number between 1 and 100. You will need an outer loop (using the same leftPad trick), and the inner logic stays exactly the same. If you want to share what you came up with, drop it in the comments.

Post a Comment