Author Posts

so I found this on the web
1..100|%{\$x=@{0='Fizz'}[\$_%3]+=@{0='Buzz'}[\$_%5];@{0=\$x;1=\$_}[[Int]!\$x]}

and I can't figure out how it does what it does... 😉 could someone explain please? I understand what the first part does, up to this thing "];@{0=\$x;1=\$_}[[Int]!\$x]}" but I don't really understand how the first part works. I know what % does and += but HOW does it work? and what the second part does and HOW?

Thank you!

I'd say this is a lesson in not writing unreadable crap for code. 😉 However, here goes:

This is really two statements, so let's split them out:

```\$x=@{0='Fizz'}[\$_%3]+=@{0='Buzz'}[\$_%5]
@{0=\$x;1=\$_}[[Int]!\$x]
```

The first line doesn't output anything, it just sets up the \$x variable, which will be either null, "Fizz", "Buzz", or "FizzBuzz", depending on the value of \$_ and whether it is divisible by 3 and/or 5.

The second line wants to output the number \$_ , if \$x is null, and otherwise output \$x. "!\$x" becomes a boolean: if \$x is \$null, !\$x will be true, and if \$x any non-empty string, !\$x is false. When you cast booleans to [int] in PowerShell, \$true becomes 1, and \$false becomes 0. The hashtable is set up so that 0 outputs the value of \$x, and 1 outputs the value of \$_.

Incidentally, if this is a "code golf" kind of thing where they wanted the code to be short, it can be trimmed a bit:

```1..100|%{\$x=@('Fizz')[\$_%3]+@('Buzz')[\$_%5];(\$x,\$_)[!\$x]}
```

This uses arrays instead of hashtables, and uses "+" instead of "+=". As long as strict mode isn't turned on (which would complain about invalid array indexes), this works the same way. The casting of a boolean to [int] is implicit as well, so you can save a few characters by not typing that part out.

Hello, thank you, but how does part 1 work, I mean, where can I read something about this @(something). What kind of construction is that?

@() is the array subexpression operator. It forces the contents of the parentheses to be evaluated as an array, even if there are 0 or 1 results returned. (If 2 or more objects were there, it would be an array anyway, which is why I was able to do away with the @ character, in the second part.)

The basic documentation of this is in the about_Operators help file (https://technet.microsoft.com/en-us/library/hh847732.aspx) .

omg, i'm retarded, sorry!

But you explained so good that even I understood (that's a rhyme)
and bear in mind I'm retarded.

Thank you, case closed!

Don't worry about it! 🙂 Like I said, this kind of code is garbage that's only useful for code golf contents (and maybe for practice at reading bad code.) In the real world, you want code to be easy to read and understand, first and foremost. Something like this:

```1..100| ForEach-Object {
\$string = ""

if (\$_ % 3 -eq 0)
{
\$string += "Fizz"
}

if (\$_ % 5 -eq 0)
{
\$string += "Buzz"
}

if (\$string -eq "")
{
\$string = \$_
}

\$string
}
```

sorry to bother you, but how in the world does this work?: what do I google? xD

```filter fizz-buzz{
@(
\$_,
"Fizz",
"Buzz",
"FizzBuzz"
)[
2 *
(\$_ -match '[05]\$') +
(\$_ -match '(^([369][0369]?|[258][147]|[147][258]))\$')
]
}

1..100 | fizz-buzz```

is that regex??

Okay, I got this one, it turned out to be pretty easy, I didn't think they were just bruteforcing this problem, basically. I thought that is some funky command encoding or aliases or something like that. What they are doing is testing if \$_ starts with 3,6 or 9 and has 0,3,6,9 or 2,5,8 and 1,4,7 or you get the idea. So if it matches it returns 1 if not 0.
so we have 2 * (1 or 0) + (1 or 0). That leads to 4 outcomes 0,1,2,3 which equates to

```\$_,
"Fizz",
"Buzz",
"FizzBuzz"```

pretty clever, but I thought its something much more complex 😉