Wednesday 30 June 2010

Programmers are suckers for a meme

Many Open Source projects have and IRC # for developers. The NetSurf project is no different. During a discussion someone jokingly suggested that one contributor should be asked to take the FizzBuzz test. Can you guess what happened next?

Ten minutes later Michael Drake posted this solid example in C which is where it all ought to have ended.


Being programmers, of course this had a predictable result. The original question, the reason for asking it and any the serious point being made in the original article were discarded. Just so everyone (including myself) could play silly buggers over our lunch break. Coders, it would seem, simply like to produce a solution even if it is only for fun.

None of these programs took more than ten minutes (except the JAVA monstrosity), are reproduced with permission and I am to blame for none of them (ok maybe just the one ;-).

First up was Rob Kendrick with the classic solution in C (his day job is as a support team lead which seems to make those programmers who cannot do this seem even more scary bad.)


Next was Daniel Silverstone who turned this Lua solution out very quickly and berated the rest of us for not following the rules ;-)


The final C solution was my own uber silly sieve implementation


Peter Howkins decided the world required a solution in PHP


When pointed out that his solution stopped at 50 he presented this vastly superior and obviously idiomatic solution


Finally after a long time James Shaw caused mental anguish and wailing with this abomination unto Nuggin.


With Luck everyone has now got it out of their system and we will never have to put up with this again (yeah right). And now you also know why Open Source projects sometimes take ages to release ;-)

10 comments:

  1. Python:

    for i in range(0, 100):
    ⠀⠀if i % 15:
    ⠀⠀⠀⠀print 'FizzBuzz'
    ⠀⠀elif i % 3:
    ⠀⠀⠀⠀print 'Fizz'
    ⠀⠀elif i % 5:
    ⠀⠀⠀⠀print 'Buzz'
    ⠀⠀else:
    ⠀⠀⠀⠀print i

    Or:

    for i in range(0, 100):
    ⠀⠀fizzed = False
    ⠀⠀if i % 3:
    ⠀⠀⠀⠀print 'Fizz',
    ⠀⠀⠀⠀fizzed = True
    ⠀⠀if i % 5:
    ⠀⠀⠀⠀print 'Buzz',
    ⠀⠀⠀⠀fizzed = True
    ⠀⠀if not fizzed:
    ⠀⠀⠀⠀print i,
    ⠀⠀print

    P.S. I used Unicode U+2800 BRAILLE PATTERN BLANK to produce significant whitespace ;)

    ReplyDelete
  2. in 1 ugly line of python

    python -c 'print "\n".join([[str(x),"fizz","buzz","fizzbuzz"][(x%3==0)+(x%5==0)*2] for x in xrange(1,101)])'

    ReplyDelete
  3. Just because no-one has yet: a factor solution!

    USING:⠀formatting⠀;
    IN:⠀fizzbuzz

    :⠀analyze-n⠀(⠀n⠀--⠀by3?⠀by5?⠀)
    ⠀⠀⠀⠀[⠀5⠀rem⠀]⠀[⠀3⠀rem⠀]⠀bi⠀[⠀0⠀=⠀]⠀bi@⠀;

    :⠀fb⠀(⠀n⠀--⠀)
    ⠀⠀⠀⠀dup⠀analyze-n⠀⠀⠀⠀
    ⠀⠀⠀⠀[⠀or⠀not⠀swap⠀and⠀]⠀2keep
    ⠀⠀⠀⠀[⠀"Fizz"⠀write⠀]⠀when
    ⠀⠀⠀⠀[⠀"Buzz"⠀write⠀]⠀when
    ⠀⠀⠀⠀[⠀"%d"⠀printf⠀]⠀when*⠀nl⠀;

    :⠀fizzbuzz⠀(⠀--⠀)
    ⠀⠀⠀⠀100⠀iota⠀[⠀1⠀+⠀fb⠀]⠀each⠀;

    ReplyDelete
  4. iframes don't work in RSS.

    ReplyDelete
  5. Perl I did this moring in the subway after reading your blog post:

    #!/usr/bin/perl

    for my $i (1..100) {
    if ($i % 3 == 0) {
    if ($i % 5 == 0) {
    print "FizzBuzz\n";
    } else {
    print "Fizz\n";
    }
    next;
    } elsif ($i % 5 == 0) {
    print "Buzz\n";
    next;
    }
    print "$i\n";
    }

    ReplyDelete
  6. Now this is really… amusing. Interestingly enough, i386 does have enough registers for this, and I got it short enough with the version with three counters (probably the fastest as well). Portable i386 assembly code (needs GNU as from approximately 1999 AD or later, and some libc) follows. Size is 98 text, 15 data, 0 bss. I hope the formatting is kept…

    /* compile with: gcc -o fb fb.S */
    .intel_syntax noprefix
    .data
    Lfizz: .asciz "Fizz"
    Lbuzz: .asciz "Buzz"
    Lnumb: .asciz "%d"
    Lnl: .asciz "\n"

    .text

    .globl printf

    .globl main
    main: push ebp
    push esi
    push edi
    xor ebp,ebp /* number counter */
    xor esi,esi /* 0‥3 */
    xor edi,edi /* 0‥5 */
    .p2align 2
    Lloop: inc ebp
    inc esi
    inc edi
    cmp esi,3
    jne Lnet3
    push offset Lfizz
    call printf
    pop eax
    xor esi,esi
    .p2align 2
    Lnet3: cmp edi,5
    jne Lnet5
    push offset Lbuzz
    call printf
    pop eax
    xor edi,edi
    jmp Lnewl
    .p2align 2
    Lnet5: or esi,esi
    jz Lnewl
    push ebp
    push offset Lnumb
    call printf
    pop eax
    pop eax
    .p2align 2
    Lnewl: push offset Lnl
    call printf
    pop eax
    cmp ebp,100
    jb Lloop
    xor eax,eax
    pop edi
    pop esi
    pop ebp
    ret

    ReplyDelete
  7. under 1 minute, one-liner in Haskell:

    main = let f n | n `mod` 5 == 0 && n `mod` 3 == 0 = "FizzBuzz" | n `mod` 5 == 0 = "Fizz" | n `mod` 3 == 0 = "Buzz" | otherwise = show n in mapM_ (putStrLn.f) [1..100]

    ReplyDelete
  8. And in ruby:

    (1..100).each { |i| puts (if i % 3 == 0 && i % 5 == 0 then "FizzBuzz" elsif i % 5 == 0 then "Buzz" elsif i % 3 == 0 then "Fizz" else i end); }

    ReplyDelete
  9. This comment has been removed by a blog administrator.

    ReplyDelete
  10. All those tests each time through the loop: what about a nice lookup table?

    #include "stdio.h"

    int main( void )
    {
    static char fb[ 15 ][ 9 ] = { "FizzBuzz" , "" , "" , "Fizz" , "" ,
    "Buzz" , "Fizz" , "" , "" , "Fizz" ,
    "Buzz" , "" , "Fizz" , "" , "" } ;
    int i ;

    for ( i = 1 ; i <= 100 ; i++ ) {
    char *s = fb[ i % 15 ] ;

    if ( *s == 0 ) {
    printf( "%d\n" , i ) ;
    }
    else {
    printf( "%s\n" , s ) ;
    }
    }

    return 1 ;
    }

    ReplyDelete