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:
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)
Post a Comment