Librería de códigos C# (Compartan aquí sus códigos)

(1/5) > >>

DarK_FirefoX:
Librería de Códigos - C#

Me he decido a crear este tema con el objetivo de ayudar a las personas a las cuales les pueda ser útil estos códigos. Mi idea es ir posteando códigos que de una manera u otra son útiles para personas que estén aprendiendo a programar en C# y tengan alguna duda. No hay otra manera de explicarlo así que voy a comenzar:

1 - Hallar el máximo número entero de un array de enteros

Aquí introducimos como parámetro al método un array de enteros llamando "numeros", aquí estará la colección de numeros en la cual queremos buscar el máximo (Dígase máximo al número más grande). Para que entiendan:

int.MinValue es una constante dentro de la clase Int32 que representa el menor valor posible representable por un entero. Este valor es: -2,147,483,648. Por lo tanto, cualquier entero representable con el tipo de dato int, será mayor o igual que la constante MinValue.
Lo que hacemos es recorrer el array de int números y vamos indexando y comprobando cada posición del array con la variable maximo (int.MinValue en un principio), en caso de que el número sea mayor le asignamos a esa variable el valor en la posición i del array (o sea, la que se está comprobando) y seguimos recorriendo el array hasta que se hayan comprobado todos los elementos del array. Luego, la variable maximo tendrá almacenado el valor máximo del array. Lo que hacemos es devolverlo.

Código
public static int Maximo(int[] numeros)
       {
           int maximo = int.MinValue;
           for (int i = 0; i < numeros.Length; i++)
           {
               if (numeros[i] > maximo)
                   maximo = numeros[i];
           }
           return maximo;
       }


2 - Hallar el segundo mayor elemento en un array de enteros

La idea es parecida a como hallar el mayor elemento, de hecho, lo que se va a hacer es recorer el array e ir buscando el mayor elemento, pero cuando se encuentre uno mayor del que ya se encontró, ese que ya se había encontrado se va a guardar en otra variable. Entonces vamos a tener dos variables, una "mayor" y otra "sMayor" (segundo mayor). La idea es el que se encuentre se pone en la variable mayor y lo que estaba en la variable mayor se pone en la variable sMayor. De esta manera vamos llevando control de las dos variables. Hay que tener en cuenta que la comparación se realiza primero si el elemento indexado es mayor que "mayor", sino, hay que comprobar si es mayor que "sMayor" pues puede darse el caso que existan elementos entre las dos una vez después que se haya asignado los valores una vez y este elemento vendría a ser el segundo mayor.
Una vez recorrido todo el array solo resta devolver la variable "sMayor"

Código
public static int SegundoMayor(int[] numeros)
       {
           int mayor = int.MinValue;
           int sMayor = int.MinValue;
           for (int i = 0; i < numeros.Length; i++)
           {
               if (numeros[i] > mayor)
               {
                   sMayor = mayor;
                   mayor = numeros[i];
               }
               else if (numeros[i] > sMayor)
                   sMayor = numeros[i];
           }
           return sMayor;
       }


3 - Invertir los elementos de un array

Invertir los elementos viene siendo como hacer un Reverse (Invertir el orden de los elementos del array). Voy a exponer como hacerlo de dos maneras, que es prácticamente lo mismo con la diferencia que en un método modificamos el mismo array y en el otro devolvemos un array nuevo.

Modificando el mismo array

Aquí, recibimos como parámetro de entrada un array (en este caso es un array de int, esto puede servir para otros tipos de datos, o incluso se podría haber hecho genérico, lo expongo con int para simplificar). Básicamente vamos a recorrer el array hasta la mitad, utilizando la facilidad de indexar un array podemos cambiar los valores. Pues el primer elemento del array sería 0 y el último a.Length -1. Lo que utilizando la variable i del ciclo, podemos ir aumentando y disminuyendo a la vez de una forma desde afuera hacia adentro y haciendo lo que se conoce como Swap (intercambio) en esos elementos. Si nos damos cuenta el último elemento siempre nos vamos a referir como a[a.Length-1-i], puesto que i va aumentando ese valor va a ir reduciéndose. Por lo tanto el objetivo es: Cambiar el primero con el último, el segundo con el penúltimo, y así sucesivamente. Este método es void, puesto que no devolvemos nada, solamente trabajamos sobre el mismo array.

Nota: Para hacer el Swap lo que hacemos es crear una variable temporal donde asignamos uno de los valores, luego en esta variable que ya guardamos, ponemos el otro elemento a intercambiar, por último, el elemento que guardamos en la variable temporal se lo asignamos a la variable de donde sacamos el valor a intercambiar.

Código
public static void InvierteV(int[] a)
       {
           for (int i = 0; i < a.Length / 2; i++)
           {
               int temp = a[i]; //Asignamos valor a la variable temporal
               a[i] = a[a.Length - 1 - i]; //Copiamos el valor de la parte trasera del array a la frontal
               a[a.Length - 1 - i] = temp; //Copiamos el valor guardado en la variable temporal a la parte trasera del array
           }
       }

Devolviendo un nuevo array

Código
public static int[] InvierteN(int[] a)
       {
           int[] newInt = new int[a.Length];
 
           //Copiamos los elementos del array al nuevo array
           for (int i = 0; i < a.Length; i++)
               newInt[i] = a[i];
 
           for (int i = 0; i < newInt.Length/2; i++)
           {
               int temp = newInt[i]; //Asignamos valor a la variable temporal
               newInt[i] = newInt[newInt.Length - 1-i]; //Copiamos el valor de la parte trasera del array a la frontal
               newInt[newInt.Length - 1-i] = temp; //Copiamos el valor guardado en la variable temporal a la parte trasera del array
           }
           return newInt;
       }

Esta forma funciona casi idéntico, solo que hacemos primero una copia del array en un array nuevo con la misma longitud y los mismos valores, para luego trabajar sobre este array y después devolverlo tras realizarle el proceso de invertir los elementos explicados en la forma anterior.

Nota: El proceso de crear la copia del array lo hago inicializando un array de la misma longitud que el que entra como parámetro y recorriendo este array y copiando los valores a este nuevo array. Quería destacar que para hacer la copia del array podíamos usar el método Array.Copy(), pasándole el array desde donde se quiere copiar, el array a donde se va a copiar y la cantidad de elementos a copiar, en este caso todos. Hubiera sido algo así:

Código
Array.Copy(a, newInt, a.Length);

De esta forma nos hubiéramos ahorrado el primer ciclo del método (aunque en términos de eficiencia es prácticamente lo mismo)


4 - EsPrimo

Básicamente esto es algo bastante utilizado, aunque esta manera de implementarlo es "sencilla" a simple vista, puede ser un proceso extremadamente largo para números muy grandes.

Código
public static bool EsPrimo(int a)
       {
          int raizDelNumero = (int)Math.Sqrt(a);
           for (int i = 2; i <= raizDelNumero; i++)
               if (a % i == 0)
                   return false;
           return true;
       }

Lo que hacemos es calcular la raiz del numero y guardarla en una variable. Utilizamos el metodo .Sqrt dentro de la clase Math. El cuál calcula la raíz cuadrada de un número. Este método devuelve un double, por eso le hacemos un cast a int (cast es una conversión forzada a un tipo de datos). El objetivo del método es recorrer todos los números desde 2 hasta la raíz del número y ver si alguno de esos números divide al número (o sea, deja resto 0 con el número). En caso de que alguno de esos números divida al número, implica que el número no es primo. Si el ciclo termina sin devolver false, entonces devolvemos true pues el numero es primo.



Bueno, aquí les dejo los cuatro primeros, luego sigo añadiendo más de acuerdo al tiempo que tenga libre. Si alguien quiere aportar sean libres de hacerlo. Esto son cosas sencillas, pero que para personas que están aprendiendo pueden ser muy útiles. Recuerden, si añaden, comentar los códigos y/o explicarlos.

Salu2s

Eleкtro:
Todos los códigos rehusables que tengo están desarrollados en VB.Net, pero éste lo convertí hace ya tiempo, así que lo comparto por aquí :P.

Es una función que sirve para darle un formato a un documento XML sin formatear (es decir, sin indentación), lo que comúnmente se denomina cómo "Beautifier" o embellecedor, el código es simple pero efectivo.

• Before/After:


• Código:
Código
using ControlChars = Microsoft.VisualBasic.ControlChars;
using Encoding = System.Text.Encoding;
using StringBuilder = System.Text.StringBuilder;
using System;
using Xml = System.Xml;
 
namespace Tools
{
   class XmlUtil
   {
       /// <remarks>
       /// *****************************************************************
       /// Snippet Title: XML Beautifier
       /// Code's Author: Elektro
       /// Date Modified: 18-February-2015
       /// *****************************************************************
       /// </remarks>
       /// <summary>Beautifies the contents of an XML document.</summary>
       /// <param name="XMLText">
       /// The XML text content.
       /// It can be an entire document or a fragment.
       /// </param>
       /// <param name="IndentChars">
       /// The string that is used to indent the XML.
       /// Default value is: <see cref="Microsoft.VisualBasic.ControlChars.Tab"/>
       /// </param>
       /// <param name="IndentOnAttributes">
       /// If set to <c>true</c>, attributes will be separated by newlines.
       /// Default value is: <c>false</c>
       /// </param>
       /// <param name="TextEncoding">
       /// The XML text encoding to use.
       /// Default value is: <see cref="System.Text.Encoding.Default"/>.
       /// </param>
       /// <returns>The beautified XML text.</returns>
       /// <exception cref="System.ArgumentNullException"></exception>
       public static string XmlBeautifier(string xmlText,
                                          string indentChars = null,
                                          bool indentOnAttributes = false,
                                          Encoding textEncoding = null)
       {
           if (string.IsNullOrEmpty(xmlText) || string.IsNullOrWhiteSpace(xmlText))
           {
               throw new ArgumentNullException(xmlText);
           }
 
           StringBuilder sb = new StringBuilder();
           Xml.XmlDocument doc = new Xml.XmlDocument();
           Xml.XmlWriterSettings settings = new Xml.XmlWriterSettings();
 
           settings.Indent = true;
           settings.CheckCharacters = true;
           settings.OmitXmlDeclaration = false;
           settings.ConformanceLevel = Xml.ConformanceLevel.Auto;
           settings.NamespaceHandling = Xml.NamespaceHandling.Default;
           settings.NewLineHandling = Xml.NewLineHandling.Replace;
           settings.NewLineChars = ControlChars.NewLine;
           settings.NewLineOnAttributes = indentOnAttributes;
           settings.IndentChars = indentChars != null ? indentChars : Convert.ToString(ControlChars.Tab);
           settings.Encoding = textEncoding != null ? textEncoding : Encoding.Default;
 
           using (Xml.XmlWriter writer = Xml.XmlWriter.Create(sb, settings))
           {
               doc.LoadXml(xmlText);
               doc.WriteContentTo(writer);
               writer.Flush();
           }
 
           return sb.ToString();
       }
 
   }
}

• Características:

   · IndentChars
      This parameter determines the spacing character(s) used to indent the XML document.

   · IndentOnAttributes
      This parameter determines whether to indent the XML attributes.

   · TextEncoding
      This parameter determines the encoding used to read the XML document.

• Modo de empleo:
Código
Encoding textEncoding = Encoding.Default;
 
string unformattedXmlDocument = File.ReadAllText("C:\\Unformatted Document.xml", textEncoding);
string formattedXmlDocument = XmlBeautifier(xmlText: unformattedXmlDocument,
                                           indentChars: new string(' ', 2),
                                           indentOnAttributes: true,
                                           textEncoding: textEncoding);
 
File.WriteAllText("C:\\Formatted Document.xml", formattedXmlDocument, textEncoding);

Saludos

DarK_FirefoX:
5 - Hallar el número primo más cercano a un número

Esté código sirve para encontrar el número primo más cercano a un entero n. En éste código utilizamos el código para encontrar un número primo expuesto anteriormente (Lo añado aquí para que no tengan que ir a buscarlo al post anterior.

Código
public static bool EsPrimo(int a)
       {
           int raizDelNumero = (int)Math.Sqrt(a);
           for (int i = 2; i <= raizDelNumero; i++)
               if (a % i == 0)
                   return false;
           return true;
       }

La idea del método es comprobar si el número entrado es primo, si lo es, entonces el mismo es el primo más cercano, sino tendremos dos variables, numeroDer y numeroIzq, lo que podemos interpretarlas y usarlas para almacenar los números que hay a la izquierda y a la derecha del número n de la entrada. El objetivo es iterar por los números a la izquierda/derecha del número de la entrada y contar las distancia que tienen entre el y el número n de la entrada. Cuando encontremos un número primo a la derecha tendremos almacenado ese número y la distancia al número n, luego haremos lo mismo hacia la izquierda. Al final comprobaremos las distancias respectivas y devolveremos el número que tenga menor distancia.

Nota: Sabemos que un número primo es un número mayor que 1 tal que tiene únicamente dos divisores naturales distintos: él mismo y el 1. Por lo que si la entrada n viene dada por un número menor o igual que 1, tendrá como primo mas cercano al 2.

Código
public static int PrimoMasCercano(int n)
       {
           int contadorDer = 0;
           int contadorIzq = 0;
           int numeroDer = n;
           int numeroIzq = n;
           if (n <= 1) return 2;
           if (EsPrimo(n)) return n;
           else
           {
                   while (!EsPrimo(numeroDer))
                   {
                       numeroDer++;
                       contadorDer++;
                   }  
                   while (!EsPrimo(numeroIzq))
                   {
                       numeroIzq--;
                       contadorIzq++;
                   }              
           }
           if (contadorPos < contadorNeg) return numeroDer;
           return numeroIzq;
 
       }


6 - Hallar el máximo común divisor de un número (MCD)

El siguiente código muestra como hallar el MCD de un número utilizando el Método de Euclides, que utiliza el algoritmo de la división. Voy a mostrarlo de manera iterativa y de manera recursiva. En la manera iterativa utilizo una función auxiliar Swap(int a, int b), para hacer un intercambio de valores de dos variables

Código
static void Swap(int a, int b)
       {
           int temp = b;
           b = a;
           a = temp;
       }

Forma iterativa

El método recibe las dos variables entre las cuales queremos el MCD. El MCD es el mayor número entero que los divide a ambos sin dejar resto.

(No voy a explicar cómo funciona el algoritmo de Euclides ni el algoritmo de la división. Asumo que lo conocen)

Lo primero que debemos hacer es comprobar si los números son iguales, en ese caso, el mismo es el MCD. Sino, comprobamos y determinamos cuál de los dos es el mayor, para comenzar con el mayor como dividendo. Luego planteamos nuestra división teniendo los términos definidos, dividendo, divisor y resto. El resto viene dado por:

Código
int resto = dividendo % divisor

Luego vamos a ir "dividiendo" mientras el resto sea distinto de 0. Para cada iteración se van a ir cambiando los valores de los términos de la división. El dividendo pasa a ser el divisor, el divisor pasa a ser el resto, y el resto pasa a ser el nuevo resto (nuevo dividendo % nuevo divisor).
Por último, vamos a signarle a la variable answer el valor del resto si este es distinto de 0, para así garantizar que cuando termine el ciclo, esta variable (que es la que se va a devolver) tenga asignado el MCD, que el algoritmo de Euclides define como el último resto distinto de 0.

 Código
public static int MCD(int a, int b)
       {
           if(a==b) return a;
           if(b>a)
               Swap(a,b);
           int dividendo = a;
           int divisor = b;
           int resto = dividendo % divisor;
           int answer = a;
           while (resto!=0)
           {
               dividendo = divisor;
               divisor = resto;
               resto = dividendo % divisor;
               if (resto != 0) answer = resto;
           }
           return answer;
       }

Forma recursiva

Gracias a la recursividad tenemos un método mucho más limpio y corto. Básicamente, el método realiza lo mismo. Comprobamos inicialmente si el resto entre ellos es 0, y si lo es retornamos b (utilizada como divisor). En caso contrario llamamos recursivo, esta vez utilizamos a b (divisor) como dividendo, y utilizamos al resto entre a y b (resto) como divisor, y así recursivamente.

Nota: Pueden preguntarse ¿Por qué no se comprueba cual es el mayor para hacer el Swap? El caso es que si a es menor que b, al realizarse la comprobación nos damos cuenta que el resto entre a y b va a ser a, entonces no va a ser 0, por lo tanto va a llamar recursivo, con b (la variable mayor) como a, y al resto entre a y b (que era a) como b

Código
static int MCD(int a, int b)
       {
           if (a % b == 0) return b;
           return MCD(b, a % b);
       }


7 - Descomposición de un número en factores primos

Descomponer un número en factores primos consiste en descomponer un número compuesto en divisores no triviales primos que multiplicados den el número.

En este código muestro como descomponer un número n en factores primos.

Nota - 1: Utilizo el método EsPrimo(), explicado anteriormente.
Nota - 2: En este código muestro el resultado en consola utilizando:

Código
Console.WriteLine()

Pueden modificarlo para que se almacenen en una lista.

Primero que todo comprobamos si el número es primo, en caso de que lo sea, no tiene otros divisores, por lo tanto, devolvemos el único divisor primo que tiene, él mismo.

Ahora, lo que vamos a hacer es ir iterando con una variable desde 2 hasta que encontremos un número que sea primo y que divida al número. En caso de que se cumplan esas dos condiciones, vamos a dividir el número por la variable i (con la cual se está iterando), vamos a devolver el valor de i pues este es el primer factor primo encontrado, y vamos a volver a hacer la variable i de nuevo 2. En caso de que el alguna de las condiciones no se cumpla, se incrementará la variable i y se realizaran las mismas comprobaciones con este nuevo valor. Estas comprobaciones se van a realizar mientras la variable numero sea distinta de 1. Como vemos, al estar dividiendo esta variable va a ir disminuyendo su valor hasta llegar a 1. En este caso terminará el ciclo.


Código
public static void DescomposicionPrimos(int n)
       {
           if (EsPrimo(n)) Console.WriteLine(n);
           else
           {
               int i = 2;
               int numero = n;
               while (numero!=1)
               {
                   if (EsPrimo(i))
                   {
                       if (numero % i == 0)
                       {
                           numero = numero / i;
                           Console.WriteLine(i);
                           i = 2;
                       }
                       else i++;
                   }
                   else i++;
               }
           }
 
       }

8 - Comprobar si un número es perfecto

Un número perfecto es un número natural que es igual a la suma de sus divisores positivos, sin incluirse a si mismo.

Nota: Aquí utilizamos también el método EsPrimo, puesto que si el número n de la entrada es primo entonces no es perfecto.

La variable suma va a ir controlando la suma de los divisores de n. Esta siempre va a comenzar ya con 1 pues el 1 divide a todos los números, por lo tanto siempre se cuenta. Vamos iterar desde 2 hasta la mitad del número. Puesto que ningún número mayor que la mitad va a dividir al número. Entonces lo que haremos es comprobar que la variable sobre la cual se está iterando deje resto 0 con n y se lo sumamos a la variable suma. una vez que termine el ciclo, devolvemos true en caso de que suma sea igual a n, o falso en caso contrario

Código
public static bool EsPerfecto(int n)
       {
           if (EsPrimo(n)) return false;
           int suma = 1;
           for (int i = 2; i <= n / 2; i++)
               if (n % i == 0)
                   suma += i;
           return suma == n;
       }

Esto son los otros 4 que he ido terminando. Seguiré luego.

Salu2s

DarK_FirefoX:
9 - Hallar el n-ésimo término de la sucesión de Fibonacci (Recursivo)

La sucesión de Fibonacci es una sucesión infinita de números naturales:

1, 1, 2, 3, 5, 8, 13, 21...

la cual viene dada por la siguiente definición recursiva:

fn = fn-1 + fn-2

donde los dos primeros valores son predeterminados:

f0 = 0 y f1 = 1

Lo que voy a mostrar es un método para calcular el n-ésimo término de la sucesión:

Código
static int Fibonacci(int n)
       {
           if (n == 0) return 0;
           if (n == 1) return 1;
           return Fibonacci(n - 2) + Fibonacci(n - 1);
       }

Este código es muy sencillo de entender (si entendemos recursividad). Primero que todo planteamos los casos base. Si n=0 retornamos 0 (caso para f0 = 0) y si n=1 retornamos 1 (caso para f1 = 1). En caso contrario devolvemos el resultado de la suma de las llamadas recursivas de Fibonacci para n-2 y para n-1. Lo cual define la ecuación recursiva.

Esta definición nos lleva al siguiente código que quiero mostrar de acuerdo con la sucesión de Fibonacci. Si nos damos cuenta, esté código realiza operaciones duplicadas, puesto que si queremos calcular el 5 término de la sucesión, debido al llamado recursivo calculamos el 4 término y el 3 término, pero a su vez el 4 término debe calcular el 3 término y el 2 término, entonces nos damos cuenta que el 3 término se va a calcular 2 veces en el árbol de recursión. Esto se conoce como subproblemas superpuestos ¿Que podemos hacer? Utilizaremos programación dinámica.

Fibonacci Dinámico

Código
static long[] fibonacci; //Para ir almacenando los valores de los términos calculados.
 
       static void Main(string[] args)
       {
           long n = long.Parse(Console.ReadLine());
           fibonacci = new long[n+1];
           Console.WriteLine(Fibonacci(n));
 
       }
 
       static long Fibonacci(long n)
       {
           if (fibonacci[n] != 0)
               return fibonacci[n];
           if (n == 1 || n==2)
               return 1;
           fibonacci[n - 2] = Fibonacci(n - 2);
           fibonacci[n - 1] = Fibonacci(n - 1);
           return fibonacci[n - 2] + fibonacci[n - 1];
       }

Bueno, lo que vamos a hacer es ir almacenando los términos que se vayan calculando en un array cuya longitud va a ser el término de Fibonacci que se quiera calcular más 1. Y el método cambia un poco.

Primero que todo revisamos si ese término ya se calculó (comprobando si el array en esa posición es distinto de 0). Si se calculó lo devolvemos. Sino, vamos a analizar los casos base, en este caso añadimos una condición con un OR, para los 2 primeros términos de la sucesión. Retornamos 1 en caso de que n=1 o n=2. Luego de esto, en vez de devolver la suma de los llamados recursivos, llamamos recursivo asignándole los valores a las respectivas posiciones en el array. Una vez calculadas/devueltas los valores, entonces se devuelve la suma de los valores contenidos en el array.

Espero esto se haya entendido


10 - Devolver el Reverse de un string

El objetivo del siguiente código es devolver un string con sus char invertidos. El método recibe un string y devuelve un nuevo string. Por lo tanto lo primero que hacemos dentro del método es crear un string que será el que se devolverá. Recorreremos el string de entrada de atrás hacia adelante con un ciclo for. Luego solo nos queda dentro del ciclo concatenarle al string recién creado cada carácter que nos vayamos encontrando en el string original por medio de la posibilidad de indexar en el string.

Código
public static string Reverse(string original)
       {
           string reverse = "";
           for (int i = original.Length-1; i >= 0; i--)
               reverse += original[i];
           return reverse;
       }

11 - Convertir de decimal a binario

Forma iterativa

Voy a mostrar como iterativamente convertir un número decimal (en este caso un int) a un número binario. La conversión de decimal a binario se realiza haciendo divisiones sucesivas por 2 al número y a sus cocientes. Luego, cuando el número a dividir sea 1 se finaliza la división y se ordena los restos en el orden inverso al que fueron apareciendo.

Lo primero que hacemos es comprobar si el número es 0, si lo es, devolvemos un string con el carácter 0. O sea, el número binario 0. Luego, lo que vamos hacer es ir almacenando los restos a medidas que aparezcan en un string que creamos dentro del método. Utilizamos un while para controlar el ciclo. Aquí utilizo un while(true), el cual va a estar corriendo siempre a no ser que se haga un break (el cual se hace). Lo primer que hacemos es establecer la condición para la cual se va a salir del ciclo, la cual es en el caso de que se divida y el número de 1. Por lo tanto concatenamos al principio el último resto, y luego el 1, que viene siendo el último número que apareció en la división. Entonces hacemos break. En caso de que no se cumpla la condición de n/2 == 1. Vamos a hacer el proceso de concatenar al principio el resto que encontremos y después dividir el número. Proceso que se ejecutará hasta que se cumpla la condición explicada anteriormente. Al final devolvemos el string.


Código
public static string DecimalABinario(int n)
       {
           if (n == 0) return "0";
           string a = "";
           while (true)
           {
               if (n / 2 == 1)
               {
                   a = n % 2 + a;
                   a = 1 + a;
                   break;
               }
               a = n % 2 + a;
               n = n / 2;
           }
           return a;
       }

Quiero que esto podría hacerse de otra forma, en vez de concatenar al principio del string, podemos concatenar al final utilizando el operador += sobre el string a devolver, solo que la hora de devolver el string lo hacemos llamando al método Reverse, que explique anteriormente.

Forma recursiva

En esta forma iterativa voy a tener una cosa a la que yo llamo: "Método portal", el cuál es el método público (que se le muestra al usuario) el cual tiene una sobrecarga (método con otros parámetros) de tipo privado.

Código
/// <summary>
       /// Método portal
       /// </summary>
       public static string DecimalABinario(int dec)
       {
           return DecimalABinario(dec, ""); //Llamamos al método
       }
 
       private static string DecimalABinario(int dec, string result)
       {
           if (dec == 0)
               return "0" + result;
           if (dec == 1)
               return "1" + result;
           return DecimalABinario(dec / 2, (dec % 2) + result);
       }

El método portal recibe el número a convertir a través de la variable dec (int) (cuyo significado semántico es "decimal"l). Entonces a partir de ahi le pasamos al método recursivo esa variable y un string vacío. Los casos bases vienen dado por si el número es 0, devolvemos 0 concatenado al principio del string, si el número es 1 devolvemos 1 concatenado al principio del string. En caso contrario se hace la llamada recursiva, donde el número que se le pasa es la el número dividido por 2 y el string es el resto que deja el número con 2 concatenado al principio del string.

Espero esto se entienda. La verdad es necesario que tengan conocimientos de recursividad para entender esto, sino, miren la forma iterativa.

12 - Convertir de binario a decimal

Convertir de binario decimal es un proceso que viene dado por la suma de las multiplicaciones sucesivas de los dígitos de un número por 2 elevado al índice que ocupa este número (comenzando por 0). Por ejemplo el número binario 1011 seria igual a 1*23 + 0*22 + 1*21 + 1*20 = 8 + 0 + 2 + 1 = 11 (decimal)

Forma iterativa

Primero que todo voy a aclarar que recibimos el número binario a través de un string, los números binarios es mejor representarlos en un string pues si la representación binaria de un número es muy grande puede no ser representable por un int.

Código
static int BinarioADecimal(string bin)
       {
           int dec = 0;
           for (int i = 0; i < bin.Length; i++)
               dec += (bin[i] - '0') * (int)Math.Pow(2, bin.Length - 1 - i);
           return dec;
       }

Primero voy a explicar ue cosa es:

Código
bin[i]-'0'

Lo que estamos aquí es convirtiendo un char a int. ¿Cómo? Pues como sabemos un char es básicamente un entero con un puntero a la tabla ASCII. A todos los chars le corresponden un valor entero. Haciéndole la substracción por el char '0' lo que hace es buscar el valor de este caracter en la tabla, el cual es el valor base y se los substrae al valor del char Código
bin[i]
, lo cual nos devuelve el número original.

Una vez entendido esto, veamos que el método lo que hace es crear un int para devolver el valor, e ir sumándole a él la multiplicación del dígito por la potencia de dos. Recorremos el string (representación binaria del número) y vamos sumándole al int creado la multiplicación del digito Código
bin[i]-'0'
por la potencia.

La potencia la calculamos utilizando el método Pow() de la clase Math. El método recibe un double que  representa la base (en este caso 2) y un double que representa el exponente (en este caso bin.Length - 1 -i. Decimos -1 pues los índices de los dígitos van desde 0 hasta la longitud -1, y decimos -i pues queremos que este valor vaya disminuyendo a medida que avancemos en el string. Aclaro que al resultado de este método se le hace un cast a int pues el método devuelve un double, y no podemos multiplicar un int por un double sin hacer la conversión.

Cuando termine el ciclo devolvemos el número entero (representación decimal del número.

Forma recursiva

Código
       /// <summary>
       /// Método portal
       /// </summary>
       static int BinarioADecimal(string bin)
       {
           return BinarioADecimal(bin, 0);
       }
 
       static int BinarioADecimal(string bin, int result)
       {
           if (bin.Length == 0)
               return result;
           return BinarioADecimal(bin.Remove(0, 1), result + (int)(Math.Pow(2, bin.Length - 1) * (bin[0] - '0')));
       }

En este método es casi lo mismo, solo con un pequeño cambio, en vez de ir recorriendo los índices vamos a utilizar el método Remove() dentro de la clase String, el cual devuelve un substring de un string con los caracteres eliminados desde una posición especificada y la cantidad que se le especifiquen.

Lo que hacemos es comprobar si el string ya está vacío, en este caso devolvemos el resultado.

Sino, llamamos recursivo con el resultado del método Remove sobre el string bin eliminándole el primer carácter. Y también le pasamos la suma de la variable result por la multiplicación del dígito (primer) por la potencia de dos.

Espero se entienda.


En cuanto tenga tiempo hago más.
Salu2s

DarK_FirefoX:
13 - Saber si una cadena (string) es palíndromo

Primero que todo ¿Qué es palíndromo? Bueno, palíndromo es una palabra, número o frase que se lee igual hacia adelante que hacia atrás.

Ejemplo: anita lava la tina (anitalavalatina)

Este código es extremadamente sencillo. Supongamos que la entrada es un string y que no tiene espacios.

Forma iterativa

Código
public static bool EsPalindromo(string cadena)
       {
           for (int i = 0; i < cadena.Length / 2; i++)
           {
               if (cadena[i] != cadena[cadena.Length - 1 - i])
                   return false;
           }
           return true;
       }

Simplemente recorremos el string hasta la mitad, pues gracias a los índices y a la propiedad Length de la clase string podemos acceder a los caracteres de la segunda mitad del string

El objetivo es comprobar el primer carácter con el último, el segundo con el penúltimo y así sucesivamente. Si se encuentra que alguno es diferente del otro, se devuelve false (no es palíndromo). Si se llega al final del ciclo sin devolver false, entonces se devuelve true (es palíndromo)

Forma recursiva:

Código
static bool EsPalindromo(string s)
       {
           int lIzq = 0;
           int lDer = s.Length - 1;
           if (lIzq >= lDer) return true;
           return s[lIzq] == s[lDer] &&
               EsPalindromo(s.Substring(lIzq + 1, lDer - 1));
       }

En la forma recursiva vamos a ir llevando un control de los índices manualmente. Utilizaremos también el método Substring() de la clase string. Este método devuelve un substring de un string dado desde una posición dada con una longitud dada.

Lo primero que hacemos es definir los índices del string. En este caso 0 y la s.Length-1. Luego comprobamos que no hayamos terminado de revisar el string completo. La comprobación viene dada por si los índices se superpusieron. Luego viene el llamado recursivo. Aqui viene dado por un AND entre si el string en las posiciones dadas son iguales y el llamado recursivo en sí. Al llamado recursivo en si se le pasa como parámetro el substring con la posición izquierda más 1 y la posición derecha menos 1. Desta forma garantizamos que seguir funcionando si en la posición actual los caracteres son iguales y solo si también es palíndromo lo que está entre esos caracteres.


14 - Saber el factorial de un número

El factorial de un número se define como el producto de todos los números enteros positivos desde 1 hasta el número.

Por ejemplo: 5! = 1*2*3*4*5 = 120

Forma iterativa

Código
public static long Factorial(long numero)
       {
           long result = 1;
           for (long i = 2; i <= numero; i++)
               result *= i;
           return result;
       }

Este código es algo relativamente sencillo. Se basa en una productoria desde 1 hasta el número. Con un ciclo for resolvemos este problema sencillamente. Creamos una variable de tipo long, puesto que el factorial de un número puede llegar a ser un número grande y puede no caber en un int. La iniciamos en 1 pues el número 1 siempre se va a multiplicar. Luego el ciclo va desde 2 hasta el número y vamos multiplicando la variable result por la variable iteradora del ciclo y asignándosela a ella misma utilizando el operador *=

Nota: Quiero aclarar que el 0! es igual a 1. Y este código funcionara perfecto, pues si el número es 0, no se ejecutará nunca la instrucción dentro del ciclo pues nunca se cumplirá la condición de iteración y no se entrará al ciclo. Por lo tanto se devolverá result = 1

Forma recursiva

Código
static long Factorial(long n)
       {
           if (n == 0) return 1;
           return n * Factorial(n - 1);
       }

Si entendemos recursividad esto sale straight-forward. El caso base es para n=0 devolvemos 1 sino, devolvemos n * la llamada recursiva del factorial de n-1. Si planteamos esto explícitamente quedaría algo así como:

n * Factorial(n - 1) * Factorial (n - 2) * ... * Factorial (n - i) * ... * Factorial(0)


15 - Saber si un año es bisiesto

Un año es bisiesto si es divisible entre 4 y no es divisible por 100, también es bisiesto si el año es divisible por 400.

Llevar esto a un código es algo muy sencillo. Aquí les dejo:

Código
public static bool EsBisiesto(int anno)
       {
           return (anno % 4 == 0 && anno % 100 != 0 || anno % 400 == 0);
       }

Realizamos la comprobación si es divisible entre 4 (deja resto 0 con 4) y no es divisible por 100 (no deja resto 0 con 100), también comprobamos si es divisible por 400 (deja resto 0 con 400). Si se cumple alguna de estas dos condiciones entonces se devuelve true, si no se cumple ninguna de las dos, se devuelve false

16 - Hallar la potencia de un número

La potencia es el resultado de multiplicar un número por sí mismo una cantidad de veces n. Un número elevado a la 0 es igual a 1.

Forma iterativa

Código
static long PotenciaIterativo(int _base, int _potencia)
       {
           long result = 1;
           for (int i = 1; i <= _potencia; i++)
               result *= _base;
           return result;
       }

Esto se plantea de una forma sencilla. Recibimos como parámetro la base y la potencia. (Utilizo el underscore (_base) para que no entre en conflicto pues en C# existe la palabra reservada base). El objetivo es multiplicar la base un cantidad de veces igual a la variable _potencia. Creamos una variable, que será que se va a devolver (long result), con el valor 1. Luego vamos a multiplicar la variable por _base dentro del ciclo que va a hacer tantas iteraciones como el valor de la variable _potencia. Cabe destacar que si la variable _potencia es 0. Nunca se ejecutará el ciclo pues no se cumplirá la condición de iteración por lo tanto no entrará al ciclo y se devolverá la variable result con el valor 1.

Forma recursiva

Código
static long Potencia(int _base, int _potencia)
       {
           if (_potencia == 0) return 1;
           if (_potencia == 1) return _base;
           return _base * Potencia(_base, _potencia - 1);
       }

Básicamente es lo mismo, planteamos los casos bases. Si la potencia es 0 entonces se devuelve 1; Si la potencia es 1 se devuelve la base. En caso contrario se multiplica la base por el llamado recursivo. El llamado recursivo va a ir convergiendo a los casos bases, pues se le resta a la potencia 1.

Nota: También puedes hacer uso del método .Pow() dentro de la clase Math. Algo así como:

Código
double potencia = Math.Pow(2, 4) //Esto eleva 2 a la 4


17 - Búsqueda binaria (colección ordenada)

Este código es algo más interesante. Este algoritmo reduce significativamente el número de comparaciones que se realiza para buscar en un array (previamente ordenado) un elemento que cumpla determinada propiedad. En este código voy a tratar con un array de int y voy a utilizar un método portal.

Código
/// <summary>
       /// Método portal
       /// </summary>
      public static bool BusquedaBinaria(int[] numerosOrdenado, int aBuscar)
       {
           return BusquedaBinaria(numerosOrdenado, aBuscar, 0, numerosOrdenado.Length - 1);
       }
 
       private static bool BusquedaBinaria(int[] numerosOrdenado, int aBuscar, int inf, int sup)
       {
           if (inf > sup)
               return false;
           int medio = (inf + sup) / 2;
           if(aBuscar==numerosOrdenado[medio])
               return true;
           if (aBuscar > numerosOrdenado[medio])
               return BusquedaBinaria(numerosOrdenado, aBuscar, medio + 1, sup);
           return BusquedaBinaria(numerosOrdenado, aBuscar, inf, medio - 1);
       }
 

En este algoritmo se compara el elemento a buscar con el elemento del medio del array, si el valor a buscar es menor que este, se repite el procedimiento en la parte del array que va desde el principio hasta el elemento del medio, sino se toma la parte del array que va desde el elemento central hasta el final del array. De esta manera se realiza sucesivamente con los pedazos hasta que cada vez van a ser más pequeños, hasta que se obtenga un intervalo que no se pueda dividir. Si el elemento no se encuentra dentro de este último entonces se deduce que el elemento buscado no se encuentra en el array.

Desde el método portal llamamos al método recursivo que tiene otros parámetros. Los parámetros son el array de los números (ordenado), el elemento a buscar, la posición inferior y la posición superior.
Lo primero que se hace es comprobar los extremos del intervalo. Si el inferior es mayor que el superior significa que el array se acabó y no se encontró el elemento, por lo tanto se retorna false. Sino se calcula la posición del medio. Luego se revisa si este elemento del medio es el que se está buscando, si lo es, se devuelve true. Entonces si esto no se cumple, vamos a revisar las mitades del array. Si el elemento a buscar es mayor que el elemento del medio se retorna el llamado recursivo pasándole como índice inferior al medio + 1 y manteniendo el superior (mitad de la derecha). En caso contrario se retorna el llamado recursivo pasándole como índice superior al medio - 1 y manteniendo el inferior.

Espero que este algoritmo se haya entendido.

Nota: Si quieres buscar en un array también puedes hacer uso de el método Contains() dentro de la clase array que devuelve un bool dependiendo si el elemento esta dentro del array. Seria algo así:

Código
int valor = 2;
bool estaElElemento = nombreArray.Contains(valor);

Mod: Agregado el método IndexOf(), utilizando el algoritmo de búsqueda binaria que a la vez devuelve el índice en el cual está el elemento buscado o devolviendo -1 si no se encuentra.

Código
/// <summary>
       /// Método portal
       /// </summary>
       static int IndexOf(int[] orderedArray, int toSearch)
       {
           return IndexOf(orderedArray, toSearch, 0, orderedArray.Length - 1);
       }
 
       static int IndexOf(int[] orderedArray, int toSearch, int min, int max)
       {
           if (min > max)
               return -1;
           int medio = (min + max) / 2;
           if (toSearch > orderedArray[medio])
               return IndexOf(orderedArray, toSearch, medio + 1, max);
           if (toSearch < orderedArray[medio])
               return IndexOf(orderedArray, toSearch, min, medio - 1);
           return medio;
       }

Tenemos un método portal al igual que en el otro método. Lo único que cambia es lo que se devuelve, que en este caso se devuelve el valor del índice. En este método comprobamos si los límites del "sub-array" en el cual estamos comprobando se sobrepasan entre ellos. Luego calculamos la posición en el medio. Y comprobamos si el valor que se busca es mayor/menor que el elemento en la posición del medio calculada. En caso de que se cumpla una u otra, se llama recursivo, ajustando los límites del sub-array. Si no es mayor o menor, entonces se devuelve el valor "medio" o sea, es el elemento que está en el medio, por lo tanto se devuelve la posición.



Luego seguiré con más. Salu2s

Navegación

[0] Índice de Mensajes

[#] Página Siguiente