## Advent Calendar - December 18, 2019

Wednesday, Dec 18, 2019| Tags: Perl

The gift is presented by Philippe Bruhat**. Today he is talking about his solutions to Task #2: FizzBuzz** of “The Weekly Challenge - 001”.

#### Write one-liner to solve FizzBuzz problem and print number 1-20. However, any number divisible by 3 should be replaced by the word fizz and any divisible by 5 by the word buzz. Numbers divisible by both become fizz buzz.

This one works by modifying the string until what’s we’re left with is the expected result:

``````perl -E '
say for map {
s/\d+/\$&%5?\$&:"\$& buzz"/e;
s/\d+/\$&%3?\$&:"fizz\$&"/e;
y/0-9//d if /\D/;
s/^ //;
\$_;
} 1 .. 20
'
``````

Same idea, but with a list, and each step being handled individually by a map expression:

``````perl -E '
say for
map @\$_ > 1 ? join( \$", splice @\$_, 0, -1 ) : @\$_,
map [ \$_->[-1] % 3 ? @\$_ : ( fizz => @\$_ ) ],
map [ \$_ % 5      ? \$_  : ( buzz => \$_ ) ],
1 .. 20
'
``````

This one is the one I actually wanted to avoid writing: the simple enumeration of all possible case:

``````perl -E '
say for map
\$_ % 5 ? \$_ % 3 ? \$_
: "fizz"
: \$_ % 3 ? "buzz"
: "fizz buzz",
1 .. 20
'
``````

And then I realized, the four cases can be seen as the four values of a two bit vector, and use that to index the array of all possible values:

`````` perl -E '
say for map
[ "fizz buzz" => buzz => fizz => \$_ ]
->[ !!( \$_ % 3 ) + !!( \$_ % 5 ) * 2 ],
1 .. 20
'
``````

We can shorten it a bit by using ! instead of !! and moving the values around:

``````perl -E '
say for map
[ \$_ => fizz => buzz => "fizz buzz" ]
->[ !( \$_ % 3 ) + !( \$_ % 5 ) * 2 ],
1 .. 20
'
``````

Using the fact that a number is divisible by 5 if it ends with 0 or 5:

``````perl -E '
say for map
[ \$_ => fizz => buzz => "fizz buzz" ]
->[ !( \$_ % 3 ) + /[50]\$/ * 2 ],
1 .. 20
'
``````

If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.