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");

}

else

Console.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)

{

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 = recurd(i + 1);

}

}

 

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();

}

}