http://www.perlmonks.org?node_id=602901

In stumbling across this disturbing writeup, the author claims that not only can the majority of comp-sci majors not solve the 'fizzbuzz' problem, but he's also seen "senior" programmers take 10 or 15 minutes to solve it:

Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

Naturally, I whipped out a quick snippet just to make sure I knew how to program:

$ perl -le 'for (1..100) {print("FizzBuzz"), next if not $_%15; \ print("Buzz"), next if not $_%5; print("Fizz"), next if not $_%3; prin +t}';

Since I'm lousy at golf, I figured I wouldn't try to shorten that, but I figured that a few of you might care to try a few rounds.

Cheers,
Ovid

New address of my CGI Course.

Replies are listed 'Best First'.
Re: Golf Challenge: FizzBuzz
by eric256 (Parson) on Mar 02, 2007 at 19:49 UTC

    Here is my variation..got 50! ;)

    #23456789 123456789 123456789 123456789 123456789 print+((Fizz)[$_%3]).((Buzz)[$_%5])||$_ for 1..100

    ___________
    Eric Hodges

      Ooh, neat! You've got a few unnecessary parentheses, though. That should be 46:

      #23456789 123456789 123456789 123456789 123456 print+(Fizz)[$_%3].(Buzz)[$_%5]||$_ for 1..100

      ... which I expect will be the winning entry. Not much cruft there.

      print "Just another Perl ${\(trickster and hacker)},"
      The Sidhekin proves Sidhe did it!

        Unfortunately, the last several entries are all missing newlines, which makes the output very hard to read.

        It seems like such output is just a little too golfed!

        Update:  Otherwise, you can still make it shorter:

        die+map{(Fizz)[$_%3].(Buzz)[$_%5]||$_}1..100

        Update 2:  As Sidhekin pointed out to me, the -l switch makes the newline problems go away.

        On an unrelated note, I thought it would be fun writing a version that doesn't use the modulo operator (%).  Originally I tried golfing it, but it didn't golf well, so here's an easy-to-read version, which makes use of divisibility tests:

        use strict; use warnings; sub divisible_by_3 { my $num = shift; while (length($num) > 1) { my $sum = 0; map { $sum += $_ } split '', $num; $num = $sum; } return $num =~ /^[0369]$/; } sub divisible_by_5 { my $num = shift; return ($num =~ /[05]$/); } sub divisible_by_15 { my $num = shift; return (divisible_by_3($num) and divisible_by_5($num)); } foreach (1 .. 100) { printf "%s\n", divisible_by_15($_)? "fizzbuzz": divisible_by_3($_)? "fizz": divisible_by_5($_)? "buzz": $_; }

        s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: Golf Challenge: FizzBuzz
by perrin (Chancellor) on Mar 04, 2007 at 18:08 UTC
    I was thinking that this is actually not as dumb an interview question as it at first appears to be. You could potentially learn something about your candidate's approach from how they solve it. Consider some of the things they might do:
    • Write a naive solution (without even the %15 trick) very quickly. Tells you this person is good at whipping out simple code.
    • Write a golfish solution. Tells you this person knows perl well, but may be too eager to show off. (An interview is probably the wrong place for golf...)
    • Write an efficient solution that minimizes the number of comparisons. Tells you this person thinks about performance. Could be a danger sign for such a small program, but it is an interview.
    • Write a very easy-to-read solution, with clear variable names and no tricks. Tells you this person thinks about maintenance.
Re: Golf Challenge: FizzBuzz
by merlyn (Sage) on Mar 02, 2007 at 16:48 UTC
    Not really a golf entry, because Perl Golf is hurting the Perl community, and I object to that, but here's my "brief" entry first attempt:
    print "$_\n" for map { ($_ % 3 ? "": "Fizz").($_ % 5 ? "" : "Buzz") || + $_ } 1..100;
      Mind to elaborate on "Perl Golf is hurting the Perl community"? What kind of aches?

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
        It contributes to the notion of perl being obscure and hard to read. It's not fair, since golf is a game, not a normal way to write code, but it still reinforces stereotypes for outsiders.
Re: Golf Challenge: FizzBuzz
by liverpole (Monsignor) on Mar 02, 2007 at 19:36 UTC
    I'll play too ... here's 59:
    map{$x=$_%3?'':'Fizz';$_%5or$x.='Buzz';warn$x||$_,$/}1..1e2

    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: Golf Challenge: FizzBuzz
by Sidhekin (Priest) on Mar 02, 2007 at 17:06 UTC

    My first shot ... how do we count?

    perl -le'print(($_%3?"":Fizz).($_%5?"":Buzz)or$_)for 1..100'

    Edit: Bah, it's practically merlyn's entry with less whitespacemore golfing. :)

    Edit2: With BrowserUK's counting standard, I get 50 if I can assume -l (as he seems to):

    sub fizzBuzz { #23456789 123456789 123456789 123456789 123456789 print(($_%3?"":Fizz).($_%5?"":Buzz)or$_)for 1..100 }

    ... and 5352 if I can't:

    sub fizzBuzz { #23456789 123456789 123456789 123456789 123456789 12 print+($_%3?"":Fizz).($_%5?"":Buzz)||$_,$/for 1..100 }

    print "Just another Perl ${\(trickster and hacker)},"
    The Sidhekin proves Sidhe did it!

Re: Golf Challenge: FizzBuzz
by BrowserUk (Patriarch) on Mar 02, 2007 at 17:07 UTC
Re: Golf Challenge: FizzBuzz
by talexb (Chancellor) on Mar 02, 2007 at 20:41 UTC

    My father's a British actuary, so growing up we had an amusing variation on this game, often played in the car during long trips. In addition to 'fizz' (3) and 'buzz' (5) we would also play with 'sausage' (7) to make the game a bit more challenging.

    Of course, after someone had made a mistake, they had to drop out, which changed what order the fizz, buzz or sausage came around to you. And I don't think we ever made it as far as the first 'fizz-buzz-sausage' -- 105.

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

    Update: OK, let's see if I can pass the code testing bit:

    #!/usr/bin/perl -w use strict; { for (1..100) { my @a; push(@a,'fizz') if ($_%3==0); push(@a,'buzz') if ($_%5==0); push(@a,'sausage') if ($_%7==0); if (@a) { print join(' ',@a) . "\n"; } else { print "$_\n"; } } }
    OK, except for a typo (I had 6 instead of 7) it worked first time. I guess I'm not too thumb-fingered.

    ps No, that was obviously *not* golfed. ;)

Re: Golf Challenge: FizzBuzz
by shmem (Chancellor) on Mar 03, 2007 at 00:29 UTC
    This is my entry on FizzBuzz:
    print+(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/for 1..100
    or in words: since for any n multiple of 3 n % 3 == 0 I just make a list which has Fizz at index 0 and nothing else in it, and pull the (n%3)th element out of that list. Same for 5. Then I concatenate them together, print the result of that if it's true (not empty string), otherwise just n; then the default input record separator. Repeat for 1 to 100.

    Straight forward and (almost) readable code (just add whitespace :-)

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Golf Challenge: FizzBuzz
by liverpole (Monsignor) on Mar 02, 2007 at 21:13 UTC
    Here's another cute way to do it, based on a version in C, which was linked to from the comments in the original article:
    print+($_,Fizz,Buzz,FizzBuzz)[3&19142723>>2*$_%30]for 1..100

    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
Re: Golf Challenge: FizzBuzz
by haoess (Curate) on Mar 02, 2007 at 19:38 UTC

    Two more:

    # 61 print substr FizzBuzz.$_,$_%3?$_%5?8:4:0,$_%15?4:8 for 1..100
    and
    # 58 print+($_,Fizz,Buzz,FizzBuzz)[!($_%3)+!($_%5)*2]for 1..100

    --Frank

Re: Golf Challenge: FizzBuzz
by Joost (Canon) on Mar 02, 2007 at 20:21 UTC
Re: Golf Challenge: FizzBuzz
by blazar (Canon) on Mar 03, 2007 at 15:13 UTC
    In stumbling across this disturbing writeup, the author claims that not only can the majority of comp-sci majors not solve the 'fizzbuzz' problem, but he's also seen "senior" programmers take 10 or 15 minutes to solve it:
    Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.

    I was quite sure I had already seen this thing. I thought it must have surely been in clpmisc. So I searched there and... much to my surprise it was actually a thread started by me! (available from Google Groups, too.)

    Actually the requirements there were slightly different: to print "'fizz' if the number is divisible by 5, 'buzz' if it is divisible by 7 and 'fizzbuzz' if it is divisible by both." (Dor all numbers from 1 up to 100.) The best solution there was given by Jay Tilton:

    print+fizz x/0|5$/.buzz x!($_%7)||$_,$/for 1..100

    It can be directly adapted to this thread's "FizzBuzz":

    print+Fizz x!($_%3).Buzz x/0|5$/||$_,$/for 1..100

    And it's 49. But Sidhekin's solution, if amended with a newline:

    print+(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/for 1..100

    scores 48, and wins!

      print+(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/for 1..100
      scores 48, and wins!
      Hmm? That's the solution I posted to FizzBuzz before this thread even started...

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

        Well done, then, I wanted to write "which is also shmem's solution", but I didn't because in this thread the other one appeared first. I won't update my node to acknowledge that you came first, since... well... these further followups do. Compliments again!

        #2345678901234567890123456789012345678901234567 warn+(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/for 1..100
        also works with one fewer characters.
        #2345678901234567890123456789012345678901234 perl -M5.01 -e 'say+(Fizz)[$_%3].(Buzz)[$_%5]||$_,for 1..100'
        But this isn't really golf since you need to add -M5.01 to the calling statement.
Re: Golf Challenge: FizzBuzz
by Moron (Curate) on Mar 02, 2007 at 17:36 UTC
    Or the slightly simplistic version that uses a precomputed LCM of 15:
    print map $_%15?($_%5?($_%3?"$_\n":"fizz\n"):"buzz\n"):"fizzbuzz\n",(1 +..100);
    update: typo corrected - thx liverpole

    -M

    Free your mind

Re: Golf Challenge: FizzBuzz
by jking (Novice) on Jun 14, 2007 at 20:59 UTC

    My solution is in my sig... this is an old thread, but I was only recently tempted by someone I met at a con to try golfing.

    It's quite addicting... I can't wait to find a way to golf mine down to at least 50 chars.

    print$_%15?$_%3?$_%5?$_:'Buzz':'Fizz':'Fizzbuzz' for 1..100;