Solving Programming Problems with PowerShell (Problem 1)

I recently read a blog post by Santiago Valdarrama about developer programming problems. He said that any programmer should be able to solve five problems in an hour or less with a programming language of his choice. My language of choice is PowerShell, which is probably not what he had in mind when he wrote the blog post. Let’s see how I get on.

Problem 1: Adding Numbers

This seemed a little trivial for a problem, but let’s see how it goes with PowerShell. The problem is this:

Write three functions that compute the sum of the numbers in a given list using a for-loop, a while-loop, and recursion.

To do this, I’m going to write the script like so:

$array = @(1, 2, 3, 4)

Add-NumbersWithForLoop -Numbers $array
Add-NumbersWithWhileLoop -Numbers $array
Add-NumbersWithRecursions -Numbers $array

Once I’m done, the script will print 10 three times. In addition, I’m going to write PowerShell advanced cmdlets so that I’m demonstrating the “best practice” of writing scripts. Let’s take a look at the first one – the for-loop:

function Add-NumbersWithForLoop
{
    [CmdletBinding()]
    [Alias()]
    [OutputType([int])]
    Param
    (
        # List of numbers to add
        [Parameter(Mandatory=$true)]
        [int[]] $Numbers
    )

    Begin
    {
        $Total = 0
    }
    Process
    {
        for ($i = 0 ; $i -lt $Numbers.Length ; $i++) {
            $Total += $Numbers[$i]
        }
    }
    End
    {
        $Total | Write-Output
    }
}

This is possibly the simplest of the three versions. I just cycle through the array, adding up numbers. If I don’t supply an array or the array isn’t integers, the in-build error checking will work. This also works if there are no entries in the list then the total will be zero – there is no error there. The while-loop needs error checking for this though:

function Add-NumbersWithWhileLoop
{
    [CmdletBinding()]
    [Alias()]
    [OutputType([int])]
    Param
    (
        # List of numbers to add
        [Parameter(Mandatory=$true)]
        [int[]] $Numbers
    )

    Begin
    {
        $Total = 0
    }
    Process
    {
        if ($Numbers.Length -gt 0) {
            $i = $Numbers.Length - 1
            while ($i -ge 0) {
                $Total += $Numbers[$i]
                $i -= 1
            }
        }
    }
    End
    {
        $Total | Write-Output
    }
}

In this case, we start at the last element and go down until we hit $Numbers[-1] – at which point, we abort the loop. Technically, I don’t need the error-check on the $Numbers.Length, but it’s a good practice to be explicit about your error checking. Don’t leave error checking to rely on default behavior – that has a habit of changing over time. The final one is recursion:

function Add-NumbersWithRecursion
{
    [CmdletBinding()]
    [Alias()]
    [OutputType([int])]
    Param
    (
        # List of numbers to add
        [Parameter(Mandatory=$true)]
        [int[]] $Numbers
    )

    Process
    {
        if ($Numbers.Length -eq 0) {
            reutrn 0
        } elseif ($Numbers.Length -eq 1) {
            return $Numbers[0]
        } else {
            return $Numbers[0] + (Add-NumbersWithRecursion -Numbers $Numbers[1..$Numbers.Length])
        }
    }
}

For recursion, I’m taking a slice of the array we are passed from the second element (remember – elements are numbered from 0) to the end and adding the total of that to the first element. Recursion needs an “out” or termination clause. In this case, if there is just one element, then I return that element and if there are no elements, I return 0.

This is the first problem in a series of five. Next time, I’ll tackle the second problem.