다음을 통해 공유


PowerShell Diversion #5: Discussion

[Follow-up discussion for PowerShell Diversion #5 ]

Here is an implementation of FizzBuzz that solves the original request to display the ‘numbers’ between 1 and 100:

foreach($i in (1..100)) {     $out = ""         if($i % 3 -eq 0)     {         $out += "Fizz"     }         if($i % 5 -eq 0)     {         $out += "Buzz"     }         if($out -eq "") {$out = $i}         $out }

Note the use of the modulus operator (‘%’), which returns the remainder of a division.  If the remainder is zero, then the number being divided (the ‘dividend’) must be an exact multiple of the number doing the dividing (the ‘divisor’).  So, this is an excellent way to check things like ‘is a number odd or even’ (calculate ‘X % 2’ – no remainder it’s even).

Here we use the modulus operator to check the FizzBuzz rules regarding divisibility by 3 or 5.  Although we also have a rule for divisible by 3 and 5, we don’t need to check that condition explicitly as it will show up naturally in the results from the two calculations we already make.

A slightly more compact version, using a switch statement:

    switch ((1..100))     {             {$_%15 -eq 0} {"FizzBuzz";continue}             {$_%3 -eq 0} {"Fizz";continue}             {$_%5 -eq 0} {"Buzz";continue}             Default {$_}     }

This makes use of a lesser-known feature of switch – the ability to supply a scriptblock as the ‘condition’ to match against.  Typically, switch is used to match numbers and simple strings, but it is much more powerful than that; the above is a fairly simple example, but the scriptblock could be much more complex, which the restriction that it return $true or $false, so switch can tell if the match was successful.  In his excellent book, PowerShell in Action, Bruce Payette (co-designer of PowerShell) rates switch as the most powerful feature in PowerShell because of this incredible flexibility.

To count the number of ‘Fizz’, etc between 1 and 1000, a simple modification of the original attempt is required:

1 .. 1000 | foreach{     $out = ""         if($_ % 3 -eq 0)     {         $out += "Fizz"     }         if($_ % 5 -eq 0)     {         $out += "Buzz"     }         if($out -eq "") {$out = $i}         $out } | Where-Object {$_ -like "*zz*"} | Group-Object

Incidentally, I mentioned in the original post that some people use this as a developer recruiting tool.  Check out some commentary on that here and here.