Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)
Mostrando entradas con la etiqueta Linq C#. Mostrar todas las entradas
Mostrando entradas con la etiqueta Linq C#. Mostrar todas las entradas

viernes, 4 de abril de 2025

El test FizzBuzz en C# y cómo abusar del lenguaje C# versión 8+

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 y que es tan aburrida y genérica que hasta una AI podría hacerla:

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

Esta primera implementación tiene un detalle: para los múltiplos de 15 imprime
Fizz
Buzz
Fizz Buzz

Si sólo se quiere "Fizz Buzz" para los múltiplos de 15 debe ser:

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 (tc == 0)
            Console.WriteLine("Fizz Buzz");
        else if (c == 0)
            Console.WriteLine("Buzz");
        else if (t == 0)
            Console.WriteLine("Fizz");
    }
    else
        Console.WriteLine(i);
}

Console.ReadLine();

La trampa en este test es que 15 es múltiplo de 3 y 5, así que se debe evaluar si es múltiplo de 15 primero si no se desea imprimir lo demás, de todos modos esto depende de si se considera correcto o no imprimir sólo "Fizz Buzz" con los múltiplos de 15 o si se acepta también que imprima "Fizz" y "Buzz" para este caso; todo depende de la salida que se desee, lo que se considera correcto en este contexto, más las pruebas unitarias... lo clásico del desarrollo de software.

Si se ignoran estos detalles y nos concentramos en el verdadero objetivo del test: saber si se es capaz de escribir un programita que haga algo y que implique un bucle con condicionales, sigue siendo mortalmente aburrido.


Para no aburrirnos tanto, acá hay una implementación que acabo de hacer, en una lambda recursiva porque le tengo manía a las lambdas recursivas:

Func<int, int> F2 = null;
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 (tc2 == 0)
                Console.WriteLine("Fizz Buzz");
            else if (c2 == 0)
                Console.WriteLine("Buzz");
            else if (t2 == 0)
                Console.WriteLine("Fizz");
        }
        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:

https://www.csharp.com/article/c-sharp-12s-switch-expressions-a-more-powerful-alternative-to-traditional-switch-st/

https://stackoverflow.com/questions/44355630/how-to-use-c-sharp-tuple-value-types-in-a-switch-statement

Lo bonito es que también admite tuplas, y esos "ifs/elses" están que me piden ser convertidos en un switch al estilo C# a partir de la versión 8. Un detalle de los nuevos switch es que ya vienen con los breaks de forma implícita, de modo que si cumplen con una de las condiciones, el código no sigue cayendo en las demás. 
Luego de juguetear un poco, otro detalle que encontré es 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 es:

Func<int, int> F2 = null;
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, > 14) => "Fizz Buzz",
            (_, 0, _, > 4) => "Buzz",
            (0, _, _, > 2) => "Fizz",
            _ => 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:
Func<int, int> F2 = null;
F2 = i =>
{
    var resultado = (i % 3, i % 5, i % 15, i);
    Console.WriteLine(resultado switch
    {
        (_, _, 0, > 14) => "Fizz Buzz",
        (_, 0, _, > 4) => "Buzz",
        (0, _, _, > 2) => "Fizz",
        _ => i,
    });
    return i == 100 ? 0 : F2(i + 1);
};
Console.WriteLine("llamando a Función Lambda Recursiva");
Console.WriteLine();
F2(0);

Y puede ser aún peor, ya dejando de lado el switch podemos abusar de los IEnumerables de C# y terminar con esperpentos como el siguiente:

    Func<IEnumerable<string>, IEnumerable<string>> F3 =
    f =>
       f.Select(c => int.TryParse(c, out _) && int.Parse(c) % 15 == 0 ? c = "Fizz Buzz" : c)
       .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);

Console.WriteLine("llamando a Función Lambda que ya no es Recursiva pero se ve más fea");
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 :)

martes, 18 de septiembre de 2018

El colador o la criba de Eratóstenes con Linq y recursivo

Ya antes había jugado con el colador de Eratóstenes, pero ahora toca hacerlo más pretencioso, menos legible y más recursivo :D
En total son tres intentos nada prácticos pero muy instructivos, pues voy a jugar un poco con funciones lambda recursivas:

// primer intento
Func<int, int> colador = null;
int[] nums = Enumerable.Range(2, 48).ToArray();

colador = n =>
{
    if (n == 8)
        return 0;
    else
    {
        nums = nums.Where(c => c == n || c % n != 0).ToArray();
        return colador(n + 1);
    }
};

colador(2);
nums.ToList().ForEach(c => Console.Write(c.ToString() + " "));

// el primer intento es una shit, modifica un array que está fuera de la función lambda.

// Acá viene el segundo intento:
Func<int, IEnumerable<int>, IEnumerable<int>> colador2 = null;
IEnumerable<int> nums2 = Enumerable.Range(2, 48);

colador2 = (n, x) =>
{
    if (n == 8)
        return x;
    else
    {
        x = x.Where(c => c == n || c % n != 0);
        return colador2(n + 1, x);
    }
};

nums2 = colador2(2, nums2);
Console.WriteLine();
nums2.ToList().ForEach(c => Console.Write(c.ToString() + " "));

// el segundo intento aún es demasiado legible.

// Acá va el tercer intento:
Func<int, IEnumerable<int>, IEnumerable<int>> colador3 = null;
IEnumerable<int> nums3 = Enumerable.Range(2, 48);

colador3 = (n, x) =>
{
    x = x.Where(c => c == n || c % n != 0);
    return (n < 8) ? colador3(n + 1, x) : x;
};

nums3 = colador3(2, nums3);
Console.WriteLine();
nums2.ToList().ForEach(c => Console.Write(c.ToString() + " "));

Console.ReadLine();



El resultado es:

jueves, 15 de octubre de 2015

Cómo obtener los items seleccionados de un CheckedListBox

Pregunta original en StackOverflow.

Mi respuesta:
En una sola línea de C# Linq:

string[] miList = chkList.CheckedItems.OfType<object>().Select(li => li.ToString()).ToArray();

Devuelve en un array de strings los textos de los items seleccionados.

miércoles, 17 de junio de 2015

Calculando el MCD de dos números de forma recursiva en C#

El algoritmo que estoy usando es bastante simple (nos lo dio un profesor durante una clase):

Se tienen dos números, "x" e "y", si son iguales retornar cualquiera de ellos.
Si x > y, hacer x = x-y;
Si x< y hacer x = y-x; y =x;
repetir hasta que x=y.

Creo que está basado en el algoritmo de Euclides. En lugar de implementarlo como un bucle, creé una función lambda recursiva:

Func<int, int, int> MCD = null;
       
        MCD = (x, y) =>
        {
            if (x == y) return x;
           
            if (x > y) return MCD(x - y, y);
            if (
x < y) return MCD(y - x, x);
           
            return 1;
        };


La forma de llamarla es:

Console.WriteLine(MCD(15,45));

lunes, 30 de marzo de 2015

Recorrer todos los controles en un contenedor: .Net y Java Swing

En este ejemplo, se quiere habilitar los controles de un contenedor en función al valor de selección de un checkbox.

En el caso de Java, el contenedor es un jPanel:

En Java 7:

for (Component c : jPanel1.getComponents())
    c.setEnabled(jcheckBox1.isSelected());
   
En Java 8:

Arrays.stream(jPanel1.getComponents()).forEach(c -> c.setEnabled(jcheckBox1.isSelected()));

Si sólo se quiere procesar los controles que sean cajas de texto:

Arrays.stream(jPanel1.getComponents()).forEach(c -> { if (c instanceof JTextField) c.setEnabled(jcheckBox1.isSelected()); } );

En el caso de .Net, el contenedor es un GroupBox:

foreach (Control c in groupBox1.Controls) 
       c.Enabled = checkBox1.Checked;

Usando Linq será:
groupBox1.Controls.Cast<Control>().ToList().ForEach(c => c.Enabled = checkBox1.Checked);

Si sólo se quiere procesar los controles que sean cajas de texto:
groupBox1.Controls.Cast<Control>().ToList().ForEach(c => { if (c is TextBox) c.Enabled = checkBox1.Checked; });

viernes, 6 de febrero de 2015

Comparación entre C# Linq y Java 8 streams

El siguiente código en C# declara un array de strings, filtra aquellos que tengan la cadens "am" y le añade tres puntos al final:


using System;
using System.Linq;

class Program
{
     static void Main()
    {
         string[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
         string[] filteredNames = names.Where(c => c.Contains("am")).Select(c => c + "...").ToArray();
         for (int i = 0; i < filteredNames.Length; i++)
               Console.WriteLine(filteredNames[i]);       
   }
}

El siguiente código en Java 8 hace exactamente lo mismo:

import static java.util.Arrays.stream;

public class HelloWorld
{
     public static void main(String []args)
     {
          String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
          String[] filteredNames = stream(names).filter(c -> c.contains("am")).map(c-> c + "...").toArray(String[]::new);
          for (int i = 0; i < filteredNames.length; i++)
                  System.out.println(filteredNames[i]);
     }
}


El código en C# corre sobre Mono v3.10 y a partir del .Net Framework 3.5. El código en Java corre a partir del JDK 1.8.

En comparación con Linq, los streams en Java son un poquitillo más complicados de usar, especialmente por la cantidad de casteos que deben hacerse. La ventaja de Linq es que sus métodos como "Select" y "Where" recuerdan a los de SQL. La ventana de los streams de Java es que sus métodos como "map" y "filter" recuerdan a los de Python.

miércoles, 1 de octubre de 2014

Modificar los datos de un DataTable con Linq en C#

Este post existe gracias a la ayuda de StackOverflow :D

Tengo un DataTable, el cual tiene una columna llamada "Campo1" con datos tipo texto. Quiero que todos los datos que coincidan con un valor sean cambiados por la cadena "Datos por Defecto".
En lugar de usar un bucle, se puede hacer con Linq:

DataTable d = MetodoQueDevuelveUnDataTable();
d.AsEnumerable().ToList<DataRow>().ForEach
   ( r =>
             {
                     if(String.Compare(r["Campo1"].ToString(), "valor que quiero cambiar") == 0)
                          r["Campo1"] = "Datos Por Defecto";
             }
   );

Lo que hace el ForEach es recorrer todas las filas y buscar aquellas donde se cumple la condición y realizar las acciones que deseemos:

DataTable d = MetodoQueDevuelveUnDataTable();
d.AsEnumerable().ToList<DataRow>().ForEach
  ( r =>
             {
                      if(String.Compare(r["Campo1"].ToString(), "valor que quiero cambiar") == 0)
                      {
                           r["Campo1"] = "Datos Por Defecto";
                           r["Campo2"] = Otro Valor;
                       }
             }
  );

Si se desea modificar un valor de uno o más campos determinados en todas las filas, sólo se quita la condición:
 
DataTable d = MetodoQueDevuelveUnDataTable();
d.AsEnumerable().ToList<DataRow>().ForEach
  ( r =>
             {
                 r["Campo1"] = "Datos Por Defecto";
                 r["Campo2"] = Otro Valor;
             }
  );

jueves, 18 de abril de 2013

Calcular los n primeros elementos del Conjunto de Wirth

Me encontré con este problema revisando la página de PuntoPeek. Aquí copio la definición del Conjunto de Wirth:
"El conjunto de Wirth es un subconjunto de los enteros positivos que cumple con la siguiente regla: el 1 pertenece al conjunto y si un numero k pertenece al conjunto entonces los numeros 2*k+1 y 3*k+1 pertenecen al conjunto."

En un primer vistazo parecía un problema que podría resolverse con un bucle, pero en realidad es bastante más complicado:
Empiezo con 1 y calculo los siguientes dos números: 2*1+1=3 y 3*1+1=4.
Mi conjunto por ahora es: [1, 3, 4]
Los siguientes dos números son: 3*2+1=7 y 3*3+1=10
Los otros dos siguientes son: 4*2+1=9 y 4*3+1=13
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13]
Calculo los dos siguientes: 7*2+1=15 y 7*3+1=22
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13, 15, 22]
Calculo los dos siguientes: 10*2+1=21 y 10*3+1=31
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13, 15, 22, 21, 31]
Calculo los dos siguientes: 9*2+1=19 y 9*3+1=28
Mi conjunto ahora es: [1, 3, 4, 7, 10, 9, 13, 15, 22, 21, 31, 19, 28]

Se puede notar que los números del conjunto de Wirth no se generan de modo ascendente, si no que el conjunto se va "rellenando" a medida que se hacen más y más cálculos. Un simple bucle que calcule los 5 primeros números del conjunto de Wirth nos dará [1, 3, 4, 7, 10] cuando la respuesta correcta es [1, 3, 4, 7, 9]. El error se hace más grande con cantidades mayores.
Otro problema es que se generan números repetidos, por ejemplo en el caso de 10*3+1 y 15*2+1.
Considerando esto, se puede comprobar que varias de la respuestas dadas en esta web son erróneas.

Para evitar el caso de números faltantes, mi algoritmo calcula el doble de los números requeridos, además de comprobar que no estén repetidos, ordena el array resultante y sólo muestra la cantidad de números solicitada.

Este es el código en Python:

def Wirth(i, n, w, k):
    if n == 1:
        return 0
    else:       
        k = w[i]
        t = 2*k + 1

        if t not in w:
            w.append(t)

        t = 3*k + 1

        if t not in w:
            w.append(t)

        return Wirth(i+1, n-1, w, k)

w=[1]
n=50

Wirth(0, n*2, w, 1)
w.sort()
w = w[0 : n]
print w




Y en C# usando Linq:

 class Program
    {
        static int Wirth(int i, int n, ref int[] w, int k, int count)
        {
            if (n == 0 || count >= w.Length)
                return 0;
            else
            {
                k = w[i];
                int t = 2 * k + 1;

                if (!w.Any(c => c == t))
                {
                    count++;
                    w[count] = t;
                }

                t = 3 * k + 1;

                if (!w.Any(c => c == t))
                {
                    count++;
                    w[count] = t;
                }
              
                return Wirth(i + 1, n - 1, ref w, k, count);
            }
        }

        static void Main(string[] args)
        {         
            int n = 50;

            int[] w = Enumerable.Repeat(0, n * 2).ToArray();
            w[0] = 1;

            Wirth(0, n, ref w, 1, 0);

            w = w.Where(c => c != 0).OrderBy(c => c).ToArray();

            for (int i = 0; i < n; i++)
                Console.WriteLine(w[i]);

            Console.Read();
        }
    }


Y obtengo la misma respuesta que PuntoPeek, cuya solución me ha gustado, es bastante elegante :D

miércoles, 27 de marzo de 2013

Code Snippet: Pequeño ejemplo del uso de Linq.Any

Definición de Linq.Any extraído de esta web:
"El operador Any se utiliza para determinar si existe un elemento dentro de una secuencia que cumpla una condición expecífica."

Pero lo que yo necesitaba era un ejemplo concreto para saber si un elemento no existe en una colección usando Linq.Any.
El siguiente código muestra cómo usar Linq.Any para saber si un elemento existe o no en una colección. Es autoexplicativo:

using System;
using System.Linq;
using System.Collections.Generic;

namespace LinqPractice
{
    class Program
    {
        static void Main(string[] args)
        {
            IEnumerable mis_nums = Enumerable.Range(0, 4);
            mis_nums = mis_nums.Select(c => c * 3);

            // mis_nums = {0, 3, 6, 9}

            if (mis_nums.Any(c => c != 7))
                Console.WriteLine("Existe al menos un número que es diferente de 7");

            if (mis_nums.Any(c => c == 9))
                Console.WriteLine("El 9 sí existe en la colección");
            else
                Console.WriteLine("El 9 no existe en la colección");

            if (!mis_nums.Any(c => c == 7))
                Console.WriteLine("El 7 no existe en la colección");
            else
                Console.WriteLine("El 7 sí existe en la colección");
          
            Console.Read();
        }
    }
}


El resultado es:

 

viernes, 22 de febrero de 2013

Algoritmo para obtener números primos de una forma funcional

Todo empezó cuando me puse a aprender Python (debido a que este curso requiere programar en ese lenguaje) utilizando Python Tools for Visual Studio. Primero debe bajarse e instalarse el Interpreter y, si no se tiene el Visual Studio, o se tiene la versión Express, hay que instalar The Visual Studio 2010 Shell Redistributable Package, y al final instalar Python Tools. Como resultado, tenemos un Python Express :D

Buscando tutoriales. hallé que en esta web proponían el siguiente método para obtener números primos (llamado "El Colador de Eratósthenes", no es el método más eficiente):

nums = range(2, 50)
for i in range(2, 8):
     nums = filter(lambda x: x == i or x % i, nums)


Luego el autor dice: "No sé de algún lenguaje que pueda hacer lo mismo con sus características propias de una forma tan compacta y legible como en Python (excepto para lenguajes funcionales)".

¡Sorpresa! En C# sí se puede:

int[] nums = Enumerable.Range(2, 48).ToArray();
for (int i = 2; i < 8; i++)
      nums = nums.Where(c => c == i || c % i != 0).ToArray();


Sólo hay que importar los espacios de nombres System y System.Linq.
:D

viernes, 14 de diciembre de 2012

Aplicando Linq a un array de Estructuras (struct)

Tengo un struct (Estructura) como el que se muestra a continuación (el constructor dentro del struct me permite asignarle valores usando la palabra reservada new):

        private struct misEjes
        {
            public int ejeX;
            public int ejeY;

            public misEjes(int x, int y)
            {
                ejeX = x;
                ejeY = y;
            }
        };

Y luego creo un array del struct misEjes de la forma:

misEjes[] ejes1 = Enumerable.Repeat(new misEjes(0, 0), 10).ToArray();

Usando Linq puedo no sólo declarar el array, si no también definir la cantidad de elementos e inicializarlos. Todo esto lo hace Enumerable.Repeat(). Como éste devuelve un IEnumerable, debo convertirlo con un ToArray(). Para este ejemplo, mi arrray tiene 10 elementos (sus índices van del 0 al 9).

Realizo varias operaciones con los elementos de mi array, y al final deseo quedarme con los que no están repetidos. Para ello hago:

ejes1 = ejes1.Distinct().ToArray();

El Distinct() devuelve todos los elementos que no se repiten. Independientemente los miembros (en este ejemplo ejeX y ejeY) de los elementos del array ejes1 pueden repetirse, pero el conjunto de los miembros de cada elemento de ejes1 (la pareja ejeX y ejeY) debe ser único.

El código completo es:

class Program
    {      
        private struct misEjes
        {
            public int ejeX;
            public int ejeY;

            public misEjes(int x, int y)
            {
                ejeX = x;
                ejeY = y;
            }
        };
       
        static void Main(string[] args)
        {           
            Random rnd = new Random(Convert.ToInt32(DateTime.Now.Millisecond));
           
            misEjes[] ejes1 = Enumerable.Repeat(new misEjes(0, 0), 10).ToArray();
           
            ejes1 =
            ejes1.Select(c=> new misEjes(rnd.Next(0, 4), rnd.Next(0, 3))).ToArray();

            foreach (misEjes em in ejes1)
                Console.WriteLine(String.Concat(em.ejeX, ",", em.ejeY));

            Console.WriteLine(String.Empty);

            ejes1 = ejes1.Distinct().ToArray();

            foreach (misEjes em in ejes1)
                Console.WriteLine(String.Concat(em.ejeX, ",", em.ejeY)); 

            Console.Read(); 
         }
    }

El resultado es:


Las líneas antes del espacio son el array original, las que están después son el array luego de aplicar Distinct(). Nótese cómo las parejas ejeX y ejeY no se repiten.

sábado, 19 de mayo de 2012

Arrays en C#

Encontré este tutorial sobre arrays en C#. Noté que le faltó mencionar un detalle: Según la documentación de msdn, un array no son sólo posiciones en memoria, son objetos que heredan de System.Array.
Primeo miramos la declaración de la clase Array:



La clase Array hereda los métodos de muchas otras clases, entre ellas IEnumerable. Es decir: todos los métodos que se pueden usar en IEnumerable, se pueden usar también con arrays.

A continuación un pequeño ejemplo:
Tengo un array de Integers (en realidad pueden ser cualquier tipo de datos: byte, double, DateTime, etc), quiero eliminar los que se repiten y convertirlos a cadenas de caracteres:

int[] misNumeros; // Contiene muchos números.
strings[] misCadenas; // aquí guardo los que no se repiten, luego de convertirlos a strings.

misCadenas = misNumeros.Distinct().Select(c => c.ToString()).ToArray();

Como los métodos Select y Distinct devuelven un IEnumerable, lo convierto a Array usando el método ToArray().

Otro ejemplo: creo un array con números del 0 al 100, realizo algunas operaciones aritméticas cualquiera, elimino los repetidos, los ordeno en orden descendente, y finalmente los convierto a un array de cadena de caracteres:

int[] nums = Enumerable.Range(0, 100).ToArray();

nums = nums.Select(c => c * DateTime.Now.Millisecond / DateTime.Now.Second + DateTime.Now.Millisecond).ToArray();

string [] calculatedNums = nums.Distinct().OrderByDescending(c => c).Select(c => c.ToString()).ToArray();

Nótese cómo siempre utilizo ToArray() para convertir de IEnumerable a Array.

sábado, 8 de octubre de 2011

Desocultando Carpetas Ocultadas por Virus con Linq

Actualización de http://electronicaamartillazos.co.nr/ (sección C#) donde muestro cómo usar Linq para crear un programita que desoculta todas las carpetas ocultas (y declaradas como carpetas de sistema) en los directorios raíz de discos duros y memorias extraíbles. Los virus que ocultan carpetas también las declaran como carpetas de sistema, de modo que no se pueden desocultar manualmente.
Este programita sirve como base para hacer programas más complejos que administren los atributos de archivos, carpetas y subcarpetas.

viernes, 29 de abril de 2011

Haciendo el Test Fizz Buzz con Linq en C#

Leyendo algunos de los muchos blogs de programación flotando por ahí, es muy probable toparse con el Test Fizz Buzz, el que yo ya he usado antes para practicar algunas cosas de programación en C#.
Y por ahí se me ocurrió hacerlo usando Linq. Todo el código es el siguiente:

using System;
using System.Linq;
using System.Collections.Generic;

namespace Operator
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] fbz = new int[100];

            for (int i = 1; i <= 100; i++)
                fbz[i - 1] = i;

            IEnumerable<string> fizbuz = fbz.Select(           
                c=> (c % 3 == 0) & (c % 5 == 0) ? "FizzBuzz" :
                    (c % 3 == 0) ? "Fizz" :
                    (c % 5 == 0) ? "Buzz" : c.ToString() );

            foreach (string c in fizbuz)
                Console.WriteLine(c);

            Console.Read();
        }
    }
}

Una cosa interesante del Linq es que tiene algo llamado "Lazy Evaluation" ó "Evaluación perezosa": la ejecución de las instrucciones no se realiza cuando se declara la interfaz IEnumerable "fizbuz", si no cuando se la recorre con el bucle foreach. De esta forma se pueden tener muchas interfaces pertenecientes a System.Collections y recién ejecutar sus códigos cuando se las recorre con un foreach.
Y luego, para cumplir con las condiciones del test, vuelvo a usar el operador ternario "?", el cual me gusta mucho porque marea cuando se lo ve las primeras veces :D :D