Saturday, May 10, 2008

C# Lambda Lazy List FizzBuzz :)

Ok, so here is my next example of an implementation of the FizzBuzz problem. I'm going to use a combination of C# 3.0's lambda expressions, lazy lists and extension methods!

First, I create a function returning a lazy list over all numbers starting from 1:
static IEnumerable<int> AllNumbers()
{
int i = 1;
while (true) yield return i++;
}
Second, I create a function returning a lazy list of strings, being pText every pCount time. I.e. null, null, Fizz, null, null, Fizz.
static IEnumerable<string> FizzBuzz(int pCount, string pText)
{
while (true)
{
for (int i = 0; i < pCount-1; i++)
{
yield return null;
}
yield return pText;
}
}

Now, I need a way of combining the values two lists, so I create an extension method for this. It takes another list and a combinator function:
static IEnumerable<T> Combine<T, TA, TB>(this IEnumerable<TA> pA, IEnumerable<TB> pB, Func<TA, TB, T> pCombineFunc)
{
var i = pA.GetEnumerator();
var j = pB.GetEnumerator();
while(i.MoveNext() && j.MoveNext())
{
yield return pCombineFunc(i.Current, j.Current);
}
}

And here is the whole FizzBuzz program, returning a list of strings being 1, 2, Fizz, 4, Buzz...:
static IEnumerable<string> FizzBuzz()
{
return AllNumbers().Combine(
FizzBuzz(3, "Fizz").Combine(FizzBuzz(5, "Buzz"), (x, y) => x + y),
(x, y) => (y != "") ? y : x.ToString());
}

To write the result to the console, I use this main function:
static void Main(string[] args)
{
foreach (string fizzBuzz in FizzBuzz().Take(100))
{
Console.WriteLine(fizzBuzz);
}
}

Thats it! Nice and easy eh? :) Hope you liked it and perhaps makes you look into C# 3.0, if you haven't already? You can always download Visual Studio 2008 C# Express for free if you want to try it out!

Edit: Changed generic parameters <T> to html-characters. Changed C# 3.5 to 3.0 (thank u Gustaf :))

1 comment:

Anonymous said...

OK, I really wrote this after the first fizzbuzz post, but in the end it was too much of a bother making a comment of it. First it required cookies, then it required Javascript, the editing window was really, really tiny, and then it didn't seem to have any code formatting that I could find, so I skipped it. But lazy lists of course made me think of it again, it being Haskell code and all... so here it is anyway. It's a fairly standard glue-functions-together kind of solution.

main = putStr . unlines . map bizzbuzz $ [1..100]

bizzbuzz n
| divides n [3, 5] = "BizzBuzz"
| divides n [3] = "Bizz"
| divides n [5] = "Buzz"
| otherwise = show n

divides n = and . map ((== 0) . mod n)