FIZZ BUZZ: MÉTODOS ANÓNIMOS, RECURSIVIDAD Y FUNCIONES LAMBDA EN C#
Un día estaba leyendo varios blogs de programación cuando me topé con esto:
http://www.variablenotfound.com/2007/02/dnde-se-han-ido-los-programadores.html
Casi como un juego, decidí hacer el algoritmo para el problema "Fizz Buzz". En realidad lo difícil no fue hallar una solución, si no hallar la mejor manera de hacerla. ¿Con una variable de control y un select...case? ¿todo metido dentro de un bucle y poniendo unos buenos if...else?
Al final éste fue mi código:
void
Main(string[]
args)
{ int t = 0, c = 0, tc = 0; for (int i = 1; i <= 100; i++) { t = i % 3; c = i % 5; tc = i % 15; if (t == 0 || c == 0 || tc == 0){ if (t == 0) Console.WriteLine("Fizz"); if (c == 0) Console.WriteLine("Buzz"); if (tc == 0) Console.WriteLine("Fizz Buzz");} elseConsole.WriteLine(i); } Console.ReadLine();} |
Y es un algoritmo que
no tiene nada de especial. Dado que los números que son divisibles entre 15 lo
son también entre 3 y 5, cuando el bucle llega a un número como 90 imprime:
Fuzz
Bizz
Fuzz Bizz
Decidí que debía hallar otras maneras de hacerlo, con el mismo algoritmo, pero cambiándole un poco la forma.
La primera fue usando recursividad, la función recursiva es la siguiente:
static int recurd(int i) {
{ t2 = i % 3; c2 = i % 5; tc2 = i % 15; { } } }
La forma de llamarla es:
static
void
Main(string[]
args)
{ int h = recurd(0); Console.ReadLine();} |
Para la versión 2.0 del lenguaje
C# se implementaron los métodos anónimos, que son pedazos de código dentro de
una función que luego pueden llamarse cuantas veces se desee (aunque en realidad
esta no es la verdadera definición: http://docentes.uacj.mx/jpaz/RefCSharp/html/a62441fa-f0a3-4acb-9aa6-93762a635275.htm ).
El código correspondiente es:
class Program{ delegate void Del(); static void Main(string[] args){ int t = 0, c = 0, tc = 0; Del ts = delegate(){ for (int i = 1; i <= 100; i++){ t = i % 3; c = i % 5; tc = i % 15; if (t == 0 || c == 0 || tc == 0){ if (t == 0) Console.WriteLine("Fizz"); if (c == 0) Console.WriteLine("Buzz"); if (tc == 0) Console.WriteLine("Fizz Buzz");} else Console.WriteLine(i);} }; Console.WriteLine("llamando a método anónimo");ts(); Console.ReadLine();} } |
La versión 3.0 del
C# nos trae las expresiones lambda y el concepto de programación funcional.
Para saber qué son recomiendo leer este tutorial:
http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda.html
http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_29.html
Yo pude hacerlo con una expresión lambda, pero quedaba muy parecido al método anónimo. Entonces se me ocurrió usar una función lambda recursiva. Eso ya era más interesante, y el código básico para implementarla está en esta otra web:
http://commanet.blogspot.com/2008/02/recursividad-annima.html
El código de la
función lambda recursiva es éste:
class Program{ delegate int FizzBuzzer(FizzBuzzer f, int n); static void Main(string[] args){ FizzBuzzer F2 = (f, i) =>{ int t2, c2, tc2; if (i == 101) return 0; else{ t2 = i % 3; c2 = i % 5; tc2 = i % 15; if (t2 == 0 || c2 == 0 || tc2 == 0){ if (t2 == 0 && i > 2) Console.WriteLine("Fizz"); if (c2 == 0 && i > 4) Console.WriteLine("Buzz"); if (tc2 == 0 && i > 14) Console.WriteLine("Fizz Buzz");} else Console.WriteLine(i); return i = f(f, i + 1);} }; Console.WriteLine("llamando a Función Lambda Recursiva"); Console.WriteLine(); //F2(F2, 0); esta forma también es válida int h = F2(F2, 0); Console.ReadLine();} } |