Rebuscando en mis archivos viejos me encontré una implementación del algoritmo FizzBuzz. Lo mencionan en esta entrada https://www.variablenotfound.com/2007/02/dnde-se-han-ido-los-programadores.html y también lo mencionan acá https://exponentis.es/el-test-de-fizz-buzz-para-contratar-programadores como uno de los tests básicos para contratar programadores.
Me divertí con este test hace casi veinte años, y por pura nostalgia pongo acá mi primera implementación de aquellos años, que es tan aburrida y genérica que hasta una AI podría hacerla:
F2 = 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 = F2(i + 1);
}
};
Console.WriteLine("llamando a Función Lambda Recursiva");
F2(0);
Lo sigo viendo aburrido, es el mismo código pero metido en una función lambda.
Por otro lado, estos días he estado revisando algunas novedades del lenguaje C# y encontré que hay otra forma de escribir la declaración switch, más info en estos enlaces:
Lo bonito es que también admite tuplas, y esos "ifs" están que me piden ser convertidos en un switch al estilo C# a partir de la versión 8. Luego de juguetear un poco, encontré que las tuplas no necesitan ser de sólo dos valores, pueden tener más. En este caso tengo tres variables qué evaluar: tc2, c2 y tc2, además del contador. El resultado: una tupla de cuatro valores (yo la llamaría "cuadrupla").
El código finalmente es:
F2 = i =>
{
int t2, c2, tc2;
if (i == 101)
return 0;
else
{
t2 = i % 3;
c2 = i % 5;
tc2 = i % 15;
var resultado = (t2, c2, tc2, i);
Console.WriteLine(resultado switch
{
(0, _, _, > 2) => "Fizz",
(_, 0, _, > 4) => "Buzz",
(_, _, 0, > 14) => "Fizz Buzz",
_ => i,
});
return i = F2(i + 1);
}
};
Console.WriteLine("llamando a Función Lambda Recursiva");
Console.WriteLine();
F2(0);
Se ve rarísimo y se puede poner peor, nos podemos deshacer de tanta variable y acortar el condicional:
F2 = i =>
{
var resultado = (i % 3, i % 5, i % 15, i);
Console.WriteLine(resultado switch
{
(0, _, _, > 2) => "Fizz",
(_, 0, _, > 4) => "Buzz",
(_, _, 0, > 14) => "Fizz Buzz",
_ => i,
});
return i == 100 ? 0 : F2(i + 1);
};
Console.WriteLine("llamando a Función Lambda Recursiva");
Console.WriteLine();
F2(0);
F3 = f =>
f.Select(c => int.TryParse(c, out _) && int.Parse(c) % 3 == 0 ? c = "Fizz" : c)
.Select(c => int.TryParse(c, out _) && int.Parse(c) % 5 == 0 ? c = "Buzz" : c)
.Select(c => int.TryParse(c, out _) && int.Parse(c) % 15 == 0 ? c = "Fizz Buzz" : c);
Console.WriteLine("llamando a Función Lambda Recursiva");
Console.WriteLine();
IEnumerable<string> f0 = F3(Enumerable.Range(1, 100).Select(c=> c.ToString()));
foreach (var item in f0)
{
Console.WriteLine(item);
}
Console.ReadLine();
La función TryParse la uso sólo para evaluar si la variable c se puede convertir a entero, de otro modo arroja error de formato. Esa característica del C# de usar el guión largo para ignorar parámetros le da al código un aspecto medio esotérico que me encanta :)