Advertisements
Posted by: jsonmez | December 19, 2009

Lambda Extensible FizzBuzz 2.0 With LINQ

Many of you have probably heard of the FizzBuzz challenge:

Jeff Atwood blogged about it here

I think it started from here

Anyway, if you don’t want to click those links and you’re not familiar with it, is a small programming problem designed to screen someone who can actually write code from someone who pretends to write code.  The problem is:

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”

The point is this is a simple problem.  Just simple enough to be interesting.  I actually got asked to solve this problem this week.  I solved it after bumbling through it way more than I should have (I was trying to think of an elegant solution on the spot.)  But it kept bugging me.  I knew there was a solution that I wanted to give it that would make me happy with feelings of maps, function pointers and linq.  Pretty much 3 of my favorite things.  So I thought about it for a bit and here is the solution I came up with (3rd cut.)

        public static void FizzBuzz()
        {
            Dictionary<Func<int, bool>, Func<int, string>> rules = new Dictionary<Func<int, bool>, Func<int, string>>();
            rules.Add(x => x % 3 == 0, x => "fizz");
            rules.Add(x => x % 5 == 0, x => "buzz");
            rules.Add(x => x % 5 != 0 && x % 3 != 0, x => x.ToString());
            rules.Add(x => true, x => "\n");

            var output = from n in Enumerable.Range(1, 100)
                         from f in rules
                         where f.Key(n)
                         select f.Value(n);

            output.ToList().ForEach(x => Console.Write(x));
        }

That’s my crack at it. If you’re not familiar with all the C# magic going on here, basically it works like this:

You have a map which maps one lambda expression which defines the rule we are checking for to a second lambda expression which is what string to return if that rule matches.
Then we have a LINQ query that does a Cartesian join on the set of numbers from 1 to 100 and the 4 rules.
Finally, we take the output and for each string we write it out.

The 4th rule in the set makes sure that after evaluating the set of rules for each number a newline gets put in.

It is kind of interesting how thinking about different ways to solve a fairly simple problem can help you think about the tools you have in new ways.

Advertisements

Responses

  1. Hey nice solution, you’re just missing the fizzbuzz part

    rules.Add(x => x % 5 == 0 && x % 3 == 0, x => “fizzbuzz”);
    rules.Add(x => x % 3 == 0 && x % 5 != 0, x => “fizz”);
    rules.Add(x => x % 5 == 0 && x % 3 != 0, x => “buzz”);
    rules.Add(x => x % 5 != 0 && x % 3 != 0, x => x.ToString());

  2. Enumerable.Range(1, 100).ToList().ForEach(i =>
    Console.WriteLine(
    (i % 3 == 0 && i % 5 == 0) ? “FizzBuzz” :
    (i % 5 == 0) ? “Buzz” :
    (i % 3 == 0) ? “Fizz” :
    i.ToString()
    )
    );

  3. Predicate isFizz = ( x => x % 3 == 0 );
    Predicate isBuzz = ( x => x % 5 == 0 );
    Predicate isJustANumber = ( x => !( isFizz( x ) | isBuzz( x ) ) );

    var rules = new Dictionary<Predicate, Func>()
    {
    { isFizz, x => “fizz” },
    { isBuzz, x => “buzz” },
    { isJustANumber, x => x.ToString() },
    { x => true, x => “\n” }
    };


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: