PowerShell
Length 15 Snippet
(1,0,'E')[$x%2]
It is a very short way to output truthy/falsey values if you are asked to determine if $x
is even. (or E
for error)
It golfs down a switch
statement
switch($x%2){0{1}1{0}2{'E'}}
It can index the array using modulo. So the basic algorithm is:
- If
$x
is even, then $x%2
is 0
, so first element in array is 1
- If
$x
is odd, then $x%2
is 1
, so first element in array is 0
- Otherwise if
$x%2
errors, it shows E
Same trick can be applied to output 1
(Truthy value) for odd number.
Length 14 Snippet
$a|% t*y|%{$_}
This combines several snippets below into a very powerful feature. Still using %
as an alias for foreach-object
, we use both of its position-0 positional parameters: -memberName
which takes a string and will return the specified member for each object and can take wildcards provided they resolve to a non-ambiguous name (String
's toCharArray
in this example); and -process
which applies a script-block to each object ({$_}
in the example).
The example above is a way to iterate through each character in a string and implicitly output it.
Length 13 Snippet
1,1|select -u
Parameters in PowerShell can both be positional and expanded. Positional meaning if the parameter flag isn't explicitly specified, it can be inferred. For example, Get-Random 10
is the same as Get-Random -Maximum 10
, because the -Maximum
parameter is positional.
Here, we're using the expandable property of parameters. Since -Unique
is the only parameter to Select-Object
that starts with -u
, we don't need to spell out the entirety of the parameter. Both of these features saves tons of bytes.
The output of this snippet, which feeds an [int]
-array into the Select-Object
cmdlet is 1
, as an [int]
.
Length 12 Snippet
0xff*2KB-2e6
PowerShell has some weird special operators that allow large numbers to be written in small number of characters.
The 0x
unary operator converts characters from hexadecimal to decimal. For example, 0xff --> 255
or 0xbeef --> 48879
.
The KB
(and MB
, GB
, TB
, and 'PB') unary operators take input on the left and multiply it by 1024
, 1048576
, 1073741824
, 1099511627776
, or 1125899906842624
, respectively. For example, instead of [int]::MaxValue
, or 2147483647
, you can write 2GB-1
.
The e
(exponentiation) binary operator basically takes the input on the left and tacks on (the input on the right) number of zeros. For example, 2e6 --> 2000000
.
The output of this snippet as written is -1477760
.
Length 11 Snippet
$a=($b=1)+1
In PowerShell, it's very important to remember that you're dealing with objects on a pipeline. This can be manipulated in several ways, and the above shows the concept of encapsulation. Commands placed in parentheses are executed first (as you'd expect), but the output of the command is left on the pipeline to be picked up later. Here, we're assigning $b
to be 1
, and then assigning $a
to be $b+1
. This snippet is equivalent to $b=1;$a=$b+1
, and shows an easy way to golf bytes anytime you're doing an assignment.
The implications here go beyond just that, however, since it's the PowerShell pipeline and so we're dealing with objects. This means that complex object creations can have nested function or procedure calls, for example calling a constructor and immediately calling a method on the resultant object, and then immediately calling a property on the result. Something like (((New-Object foo).bar()).GetBaz()).baz
is perfectly legitimate. In some cases, you don't even need to assign the object to a variable.
Additionally, since anything left on the pipeline is implicitly printed after execution, this means you can accumulate data on the pipeline and print for essentially free. For an easy example, a simple accumulator from 1 to 10 (prints 1
, then 3
, then 6
...) can be 1..10|%{($a+=$_)}
vs 1..10|%{$a+=$_;$a}
, saving a byte, but can save significantly more in other situations. Since we're talking about output, this is a good time to bring up that nearly every output to the console/shell in PowerShell includes a newline (technically \r\n
because it's Windows), so if the challenge requires separators we get that for free, too.
Length 10 Snippet
$a,$b=1..9
PowerShell has the capability to do multiple assignment. In the above snippet, $a
will be 1
, an int, while $b
will be (2,3,4,5,6,7,8,9)
, an int-array. This has the ability to save lots of bytes if you're looking for particular items -- for example, $a,$b=-split$somestring
will split $somestring
on whitespace, store the first word in $a
and the rest in $b
. Very useful if you're looping through a string, for example, or re-manipulating the rest of the string in some fashion.
Length 9 Snippet
(4,9)[$a]
PowerShell has very loose type casting. Very loose. We can thus abuse this typecasting to transform array-indexing (as the above) into an if
/else
statement. For this snippet, if $a
will somehow evaluate to a truthy value (a non-zero number, a non-empty string, any other non-$null
variable, etc.), the Boolean result will be typecast to a 1
and so the 9
will be selected. Conversely, if $a
evaluates falsey, the 4
will be selected. This is PowerShell's x?y:z
style ternary if, and is significantly shorter than the equivalent if($a){9}else{4}
. It's rare for an actual if
/else
statement to show up in PowerShell golfing.
Length 8 Snippet
$c+=++$i
A simple example showing a couple basic operations. PowerShell has both pre- and post- increment and decrement operators (++
and --
), and they function pretty much like you'd expect, except when it comes to uninitialized variables. Running the above snippet in a brand-new shell will result in ++$i
evaluating first as $null + 1 = 1
and storing in $i
, then adding that result to $c
(also $null
), which makes $c
equal to 1
as well. Flip the pre-increment to be a post-increment and you get a different result, with $c = 0
and $i = 1
, but with $c
cast as an Int32
. This null-arithmetic is a sneaky way of shaving a couple bytes here or there, especially when it comes to not needing to check if a variable already is initialized.
Length 7 Snippet
,'a'*$b
Yeah, so that's a thing. No, really. It's the PowerShell comma operator and it's used to create arrays. As an inline (binary) operator, it creates multi-element arrays, as in $myArray = 1,2,3
. As a unary operator, it creates an array with one member, as in $myArray = ,1
. In both instances $myArray.GetType()
will tell us that it's a System.Array
object. Here, we're coupling this with operator overloading (multiplication, specifically) to create an array of length $b
with each element equal to 'a'
-- that is, we can create and pre-populate an array in one go. It's important to note that the array element is evaluated once and then multiplied, so you can't do something fancy like $a=1;$b=5;,($a++)*$b
and expect an array 1,2,3,4,5
. Bummer.
Length 6 Snippet
$a-gt2
OK, pretty simplistic, but this is a continuation of the below concepts. In addition to the usual +-*/
operator overloading, PowerShell comparison operators (-le -eq -gt
etc.) are overloaded, too. As are most other "basic" operators.
Let's suppose that $a=3
, an int. Then, the above snippet will result in $TRUE
as it's comparing "is 3 greater than 2?" So far, so standard. However, let's take $a=(0,1,2,3,4,5)
an array of int's from 0 to 5. In this case, the above snippet will result in an array (3,4,5)
- that is, it constructed a new array and populated it with all elements of $a
that are individually greater than 2
. Have a constructed array already and want to know how many elements are equal to 0? Try ($a-eq0).Count
. Want the biggest element in the array that's smaller than a certain value? How about ($a-lt4|sort)[-1]
(using our "last element" trick from Snippet 4).
This sort of operator overloading continues to other objects, too, not just arrays and ints. $StringA -gt $StringB
will categorize the two strings alphabetically. $CharA -gt $CharB
calculates based on their ASCII value. And on and on and on. Pretty much any object in PowerShell can be compared like this.
As a bonus, in most cases, if the right-hand operand can be parsed appropriately, you can mix and match types like you can with normal arithmetic operators. As an example, $DateA -lt "2015/12/17"
will implicitly parse the right-hand string into a .NET datetime
object to calculate comparison.
Combined, the Length 5 and Length 6 snippets allow PowerShell codegolf answers to be very loose with type-casting, which cuts out a tremendous amount of bytes.
Length 5 Snippet
$a+$b
"What, really? The plus-sign is what you're showcasing? Phaw!" OK, OK, put down your torches and pitchforks, and hear me out. I'm showcasing operator overloading. "Well, so what, plenty of other languages have that! Plus, you showed that for your Length-1 Snippet!" Yeah, but that needs to also be coupled with PowerShell's powerful implicit casting and implicit parsing.
Operations like the above snippet in PowerShell take on the characteristics of the left-hand side operand. Suppose $a='123'
and $b=4
, with the first as a string and the second as an int. With the above snippet, the result will be 1234
as a string. Flip the order $b+$a
and PowerShell will implicitly parse the string object to turn it into an int, and the result will be 127
as an int.
While this is powerful, and allows you to abuse plenty of different operators for nefarious codegolf purposes, it has the quirk feature that operators are not commutative. In other words, ($a+$b) -eq ($b+$a)
will return False
in lots of cases.
Length 4 Snippet
[-1]
A secret weapon used when indexing arrays or strings or the like to retrieve "the last element." We don't even need to know the length of the array. Want the second-to-last element? Use [-2]
instead. And so on.
One example where this comes in handy is in finding the maximal of a list of numbers. Suppose we previously stored them in $x
. PowerShell already has an alias for Sort-Object
as sort
, thus, we can do ($x|sort)[-1]
to pull out the maximal item from $x
, and we don't even care or know how many items are in $x
, and it's significantly shorter than the "regular" method of ($x|measure -maximum).Maximum
.
Length 3 Snippet
iex
The command iex
is an alias for Invoke-Expresssion
, and is similar to an eval()
style statement. However, it has implications for codegolf in that it can take parameters or pipeline input (because remember, the pipeline hands off objects, not text).
As a simple example, suppose I need to sum the numbers from 1 to 10. I could write 1+2+3+4+5+6+7+8+9+10
, but at 20 bytes that's pretty lengthy. I know I can get a range of numbers using the ..
range operator, such as 1..10
, but now I essentially have an array of integers. I can concatenate them together with the join
operator, like so 1..10-join'+'
, and now I have a string that can be fed into iex
as 1..10-join'+'|iex
, for 17 bytes. This simple example shows how very complex commands can be dynamically constructed rather than hardcoded, but still be executed as if they were coded directly, and can significantly cut down on byte-count.
Length 2 Snippet
$_
This was already introduced below in the Length-1 snippet, but it's important enough to reiterate here. Another strong suit that gives PowerShell advantages in codegolfing is the concept of automatic variables. That is, variables that are implicitly created in the background by the system. Here, the $_
variable stands for "the current object in the pipeline." Essentially, it's a variable that is a dynamic placeholder for whatever object we're currently manipulating.
In the example loop 1..1e4|%{$_%5}
, the $_
variable first holds the integer 1
, then 2
, then 3
, etc. The power is more evident when dealing with a collection of different objects - $_
could be a string, an int, a custom PSObject holding the entire Windows System Event Log, a TCP/IP socket object, etc., all dynamically typed as the situation changes.
Length 1 Snippet
%
The other answer used a pipe |
for the Length-1 snippet, and that's probably the most important 1-symbol snippet for 99% of use cases, but the %
is functionally way more powerful for codegolf purposes, and introduces two important concepts.
The first is one of PowerShell's hidden codegolf weapons, aliasing, which significantly cuts down code length. Here, the %
character is a standard alias for ForEach-Object
, and allows us to create loops with very little code overhead.
The second is operator overloading. In PowerShell, as in other languages, the %
operator stands for modulo -- 3%2
will return 1
as an example. However, thanks to a strongly/weakly typed system (more on that later), and strong syntax requirements, the same character serves double-duty.
For example, 1..1e4|%{$_%5}
is a loop that will generate and output a 123401234012340...
string that's 10,000 characters long (with newlines in between, more on that later).
I've already rambled at length about the differences between ForEach
and ForEach-Object
, so I won't redo that here.
Factoid
Windows PowerShell had its origins over a dozen years ago (and actually just had its 9-year release anniversary; the original release was 14/Nov/2006) as Monad and the Microsoft Shell. I highly recommend reading the Monad Manifesto, originally published in August of 2002, for an amazing insight into the development process and reasoning behind naming conventions and features that developed to make PowerShell what it is today.
Bonus Factoid -- Even from the very beginning, there was pushback from hardcore users regarding the name change from Monad to PowerShell, including some pundits calling it a fad that would never catch on.