Like many of you, I dream about hitting the lottery and retiring to live the good life. Unfortunately I rarely play so I guess my odds are winning are pretty slim. But for the latest installment of Friday Fun, I thought I would have PowerShell help me pick some numbers for PowerBall. It is not as easy as you might think and you might pick up a thing or two about objects, arrays and loops.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
To play Powerball you need to pick five numbers between 1 and 59 and 1 PowerBall number between 1 and 42. The PowerBall number is easy to get from PowerShell with Get-Random.
[cc lang="PowerShell"]
PS C:\> Get-Random -Minimum 1 -Maximum 42
41
[/cc]
Getting the 5 primary numbers is a little trickier. The Get-Random cmdlet has a -Count property, but it doesn't work when you need to specify a minimum and maximum range. Here's one way we can get 5 numbers.
[cc lang="PowerShell"]
1..5 | foreach {Get-Random -Minimum 1 -Maximum 59}
[/cc]
Or you could use a For loop:
[cc lang="PowerShell"]
for ($i=1;$i -le 5;$i++) {
Get-Random -Minimum 1 -Maximum 59
}
[/cc]
But there's no guarantee you won't get a duplicate number. We could try increasing the total numbers and then selecting 5 unique.
[cc lang="PowerShell"]
1..10 | foreach {Get-Random -Minimum 1 -Maximum 59} | Select -Unique -first 5 | Sort
[/cc]
But even this isn't foolproof. I suppose I could increase the range but theoretically I believe I could still end up with duplicates or actually not enough numbers. Perhaps a Do loop would help.
[cc lang="PowerShell"]
$numArray=@()
do {
$i=Get-Random -Minimum 1 -Maximum 59
if ($numArray -notcontains $i) {
$numArray+=$i
}
} Until ($numArray.Count -eq 5)
[/cc]
I'll start out with an empty array. In the Do loop, Get-Random returns a number, $i. I then use the -NotContains operator to see if the number already exists in the array. If it doesn't, ie the evaluation is True, then the number is added to the array using the += operator. This process continues until the total number of elements in $numArray is 5. This should guarantee 5 unique numbers between 1 and 59.
Now that we can get the numbers, let's bundle the functionality. We might use New-Object and use the $numArray variable we just populated.
[cc lang="PowerShell"]
New-Object PSObject -Property @{
Numbers=$numArray | Sort
PowerBall=Get-Random -Minimum 1 -Maximum 42
}
[/cc]
I could create a function to wrap everything up but let's mix it up and use a scriptblock which will give us the same pipelined result.
[cc lang="PowerShell"]
PS C:\> $pb={$numArray=@()
>> do {
>> $i=Get-Random -Minimum 1 -Maximum 59
>> if ($numArray -notcontains $i) {
>> $numArray+=$i
>> }
>> } Until ($numArray.Count -eq 5)
>>
>> New-Object PSObject -Property @{
>> Numbers=$numArray | Sort
>> PowerBall=Get-Random -Minimum 1 -Maximum 42
>> }
>> }
>>
PS C:\> &$pb
PowerBall Numbers
--------- -------
10 {7, 26, 28, 40...}
[/cc]
Formatting is a bit tricky because the Numbers property is an array. Here's on solution that instructs PowerShell to treat the Numbers property as a string:
[cc lang="PowerShell"]
PS C:\> &$pb | Select Powerball,@{Name="Numbers";Expression={$_.Numbers -as [string]}} | fl
PowerBall : 36
Numbers : 16 42 46 49 55
[/cc]
Not too bad. In fact, I might as well wrap this up as well in a script block.
[cc lang="PowerShell"]
PS C:\> $play={&$pb | Select Powerball,@{Name="Numbers";Expression={$_.Numbers -as [string]}} | fl}
PS C:\> &$play
PowerBall : 17
Numbers : 1 16 33 34 55
[/cc]
I can even pick numbers for 5 games at once:
[cc lang="PowerShell"]
PS C:\> 1..5 | foreach {&$play}
PowerBall : 33
Numbers : 1 5 14 35 37
PowerBall : 25
Numbers : 16 25 36 44 45
PowerBall : 15
Numbers : 16 27 28 34 45
PowerBall : 23
Numbers : 19 41 42 51 57
PowerBall : 14
Numbers : 4 15 24 47 51
[/cc]
Formatting is perfect, but I hope you get the idea. I guess I should pipe my numbers to Out-Printer and head to the store and if you win with my PowerShell PowerBall picks, I hope you'll remember me. 😉