Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - DarK_FirefoX

#331
Exactamente, en mi opinion: no creo que sea necesario más emoticons de los que hay ahora.

Salu2s
#332
27 - Calcular el determinante de una matriz cuadrada de orden n

Voy a mostrar un código recursivo para calcular el determinante de una matriz cuadrada de orden n. No voy a explicar tan en detalle que cosa es el determinante pues son conocimientos "básicos" de algebra que deben saber si necesitan utilizar esté código.

Veamos que:

Sea A una matriz cuadrada; asociada a esa matriz hay un número llamado determinante, que se simboliza por |A| o det(A) y que se calcula de la siguiente forma:

- Si el orden de A es 2 el determinante es el producto de los elementos de la diagonal principal menos el producto de los elementos de la diagonal secundaria:

Ej:

A = (a00, a01)
      (a10, a11)

Luego: det(A) = a00*a11 - a10*a01

- Si el orden de A es 3 el determinante se calcula utilizando la llamada Regla de Sarrus, según la cual si A es la matriz de orden 3:

A = (a00, a01, a02)
      (a10, a11, a12)
      (a20, a21, a22)

y: det(A) = a00*a11*a22 + a01*a12*a20 + a02*a10*a21 - a02*a11*a20 - a01*a10*a22 - a00*a12*a21

Ahora, si el orden de la matriz es superior a 3 el determinante se reduce al de una matriz de orden 3 o de orden 2 de la siguiente manera (que es la que vamos a implementar):

A partir de la matriz cuadrada arbitraria A, si removemos la fila i y la columna j obtenemos una nueva matriz de orden (una unidad) menor que la matriz A y que la vamos a denotar como Aij, cuyo determinante det(Aij) recibe el nombre de menor complementario del elemento aij. Si a este det(Aij) le acompañamos de su signo (-1)i+j tenemos el adjunto de aij

Resumiendo:

Menor complementario de aij = det(Aij)
Adjunto de aij = cij = (-1)i+j*det(Aij)

Entonces, si A es una matriz cuadrada de orden mayor que 3 el determinante de A se obtiene eligiendo una fila o columna arbitraria de A y multiplicando a cada elemento de esta por su adjunto. De esta forma, si elegimos la fila i, el determinante de A es:

det(A) = SUMATORIA(desde i, j=1 hasta n)(aij * (-1)i+j * det(Aij))

Espero esto se haya entendido, trate de explicarlo lo más sencillo posible.

Ahora vamos al código:

Vamos a tener varios métodos con las siguientes signaturas:

Código (csharp) [Seleccionar]
public static int Determinant(int[,] matrix)
static int DeterminantOrder2(int[,] matrix)
static int DeterminantRec(int[,] matrix)
static void FillMatrix(int[,] matrix, int[,] toFill, int row, int column)


Como podemos observar el método Determinant() va a ser el método portal, luego tenemos para calcular el determinante de una matriz de orden 2, luego para calcular el determinante de una matriz de orden mayor que 2 y el último es un método auxiliar para rellenar la matriz adjunta de los menores.

Código (csharp) [Seleccionar]
public static int Determinant(int[,] matrix)
        {
            //Comprobamos que sea cuadrada
            if (matrix.GetLength(0) != matrix.GetLength(1))
                throw new ArgumentException("La matriz debe ser cuadrada");
            //Vemos si es de orden 2
            if (matrix.GetLength(0) == 2)
                return DeterminantOrder2(matrix);
            else
                return DeterminantRec(matrix);

        }


En este ^^ método lo primero que hacemos es comprobar que la matriz sea cuadrada, para esto comprobamos el valor del método .GetLength(), el cual devuelve un int que representa la cantidad de elementos en cada dimensión, o sea el orden de la matriz horizontal y vertical. En este caso tenemos dos dimensiones, por lo tanto comprobamos que si se cumple que:

Código (csharp) [Seleccionar]
matrix.GetLength(0) != matrix.GetLength(1)

Entonces lanzamos una excepción pues la matriz no es cuadrada.

Luego, ya que sabemos que la matriz es cuadrada vamos a comprobar si es de orden 2 y llamamos al método correspondiente, sino es de orden mayor y llamamos al método recursivo.

Veamos primero el método DeterminantOrder2():

Código (csharp) [Seleccionar]
static int DeterminantOrder2(int[,] matrix)
        {
            return (matrix[0, 0] * matrix[1, 1]) - (matrix[0, 1] * matrix[1, 0]);
        }


Este método es muy sencillo lo cual no es necesario explicar nada. (Revisen arriba como se calcula el determinante de orden 2)

Ahora, vamos con el método DeterminatRec() que viene a ser "el más complicado", lo pongo entre comilla, porque no es más que una representación en código de la ecuación que les presenté antes para calcular el determinante de orden mayor que 2:

Código (csharp) [Seleccionar]
static int DeterminantRec(int[,] matrix)
        {
            //Caso de parada que sea de orden 2 y lo calculamos con el método para
            //el determinante de orden 2
            if (matrix.GetLength(0) == 2)
            {
                return DeterminantOrder2(matrix);
            }
            else
            {
                int det = 0; //Inicializamos una variable para almacenar el valor del determinante

                //En este ciclo recorremos una fila para para obtener el adjunto de cada elemento
                //de esta fila así calcular el determinante de este fijando cada elemento de la fila
                //0
                for (int i = 0; i < matrix.GetLength(1); i++)
                {
                    //Creamos una matriz para rellenarla con la matriz para luego calcular su
                    //determinante llamando recursivo. Esta matriz tiene un orden menor (en una
                    //unidad) que la matriz original
                    int[,] minor = new int[matrix.GetLength(0) - 1, matrix.GetLength(1) - 1];

                    //Aquí llamamos al método auxiliar que se encarga de rellenar la matriz auxiliar
                    FillMatrix(matrix, minor, 0, i);

                    //Aquí lo que vamos a definir si lo que se hace es sumar o restar. Esto es una
                    //manera de representar el cambio de signo que trae consigo el (-1) elevado a
                    //i+j. En este caso como utilizamos la fila 0 siempre, ese número va a ser
                    //positivo solo cuando estemos en una columna (j) que sea par, negativo en
                    //caso contrario
                    if (i % 2 == 0)
                        //Aquí lo que hacemos es multiplicar el valor del elemento en cuestión
                        //por el  adjunto teniendo en cuenta el signo correspondiente y se lo
                        //sumamos a la variable det (en el else es lo mismo lo que con el signo
                        //negativo). Aquí es donde está la llamada recursiva pues hay que calcular el
                        //determinante de la matriz "minor"
                        det+= (matrix[0, i]) * (DeterminantRec(minor));
                    else
                        det+= (-matrix[0, i]) * (DeterminantRec(minor));
                }
               
                //Una vez que ya recorrimos toda la fila, devolvemos el determinante
                return det;
            }
        }


Ya explique todo en los comentarios del código.

Ahora veamos el método FillMatrix():

Este método recibe la matriz desde la cual se van a sacar los valores, la matriz donde se van a copiar (de un orden menor en una unidad), la fila y la columna que se va a eliminar:

Código (csharp) [Seleccionar]
static void FillMatrix(int[,] matrix, int[,] toFill, int row, int column)
        {
            //Ciclo anidado para recorrer la matriz desde la cual se van a sacar los valores
            for (int i = 0; i < matrix.GetLength(0); i++)
            {
                for (int j = 0; j < matrix.GetLength(1); j++)
                {
                    //Si estamos en una fila menor a la que se va a eliminar
                    if (i < row)
                    {
                        //Si estamos en una columna menor a la que se va a eliminar
                        if (j < column)
                            toFill[i, j] = matrix[i, j]; //Copiamos el valor normalmente
                        else
                            if (j > column)
                              //En este momento estamos en una fila menor a la que se va a
                              //eliminar pero por encima de la columna a eliminar, por lo tanto
                              //se saca el valor de la matriz y se coloca en una columna con una
                              //unidad menos (j-1)
                              toFill[i, j - 1] = matrix[i, j];
                    }
                    else
                    //Si estamos en una fila mayor a la que se va a eliminar
                    if (i > row)
                    {
                        //Si estamos en una columna mayor a la que se va a eliminar
                        if (j < column)
                            //En este momento estamos por encima de la fila a eliminar pero por debajo
                            //de la columna a eliminar, por lo tanto tenemos que quitarle una unidad a la fila
                            //(i-1)
                            toFill[i - 1, j] = matrix[i, j];
                        else
                            if (j > column)
                              //Aquí estamos por encima tanto de la fila como de la columna a eliminar por lo
                              //tanto le quitamos una unidad tanto a las filas como a la columna (i-1, j-1)
                              toFill[i - 1, j - 1] = matrix[i, j];
                    }
                }
            }
        }


Espero que este código se haya entendido, sino, ya saben que pueden preguntar, opinar y/o criticar.

Quizás no sea la mejor manera (complejidad temporal) de hacerlo, si tienen alguna sugerencia será bienvenida.

Espero seguir subiendo códigos pronto.

Salu2s
#333
26 - Evaluar una expresión en Notación Posfija (Notación Polaca Inversa)

Primero que todo, ¿Qué es la Notación Posfija (Notación Polaca Inversa)? Pues, es un método algebraico alternativo de introducción de datos, en está notación primero están los operandos y después viene el operador que se va a utilizar para realizar el cálculo sobre los operandos. En esta notación no se necesitan utilizar paréntesis para indicar el orden de las operaciones.

Veamos un ejemplo de notación posfija:

'4' '2' '10' '+' '*' '5' '-' = '43'

Para implementar esto, primero veamos el algoritmo que se utiliza:

Citar
-Si hay elementos en la bandeja de entrada
  -Leer el primer elemento de la bandeja de entrada.
    -Si el elemento es un operando.
      -Poner el operando en la pila.
    -Si no, el elemento es una función (los operadores, como "+", no son más que funciones que toman dos argumentos).
      -Se sabe que la función x toma n argumentos.
      -Si hay menos de n argumentos en la pila
        -(Error) El usuario no ha introducido suficientes argumentos en la expresión.
      -Si no, tomar los últimos n operandos de la pila.
      -Evaluar la función con respecto a los operandos.
      -Introducir el resultado (si lo hubiere) en la pila.
-Si hay un sólo elemento en la pila
  -El valor de ese elemento es el resultado del cálculo.
-Si hay más de un elemento en la pila
  -(Error) El usuario ha introducido demasiados elementos.

^^ Fuente: Wikipedia

En la implementación que hice, que estoy seguro, no es la mejor, solo tuve en cuenta los operadores +, -, *, /. Pueden añadirle más operadores para la raíz, potencia, etc.

Código (csharp) [Seleccionar]
static long EvalPosFixed(string[] exp)
        {
            Stack<long> values = new Stack<long>();
            long first, second = 0;
            for (int i = 0; i < exp.Length; i++)
            {
                switch (exp[i])
                {
                    case "+":
                        if (values.Count < 2)
                            throw new Exception("There are not enough arguments to operate");
                        second = values.Pop();
                        first = values.Pop();
                        values.Push(first + second);
                        break;
                    case "-":
                        if (values.Count < 2)
                            throw new Exception("There are not enough arguments to operate");
                        second = values.Pop();
                        first = values.Pop();
                        values.Push(first - second);
                        break;
                    case "*":
                        if (values.Count < 2)
                            throw new Exception("There are not enough arguments to operate");
                        second = values.Pop();
                        first = values.Pop();
                        values.Push(first * second);
                        break;
                    case "/":
                        if (values.Count < 2)
                            throw new Exception("There are not enough arguments to operate");
                        second = values.Pop();
                        if (second == 0)
                            throw new DivideByZeroException("Can't divide by 0");
                        first = values.Pop();
                        values.Push(first / second);
                        break;
                    default:
                        values.Push(long.Parse(exp[i]));
                        break;
                }
            }
            if (values.Count > 1)
                throw new Exception("The expression had more arguments than it should have");
            return values.Peek();
        }


El método no tiene nada complicado, recibe un array de string, el cual representa la expresión posfija, donde cada elemento del array representa un operando o un operador. En el método se recorre el array y se hace un switch para identificar los operadores. Lo demás se rige al algoritmo expuesto anteriormente.

Nota: No vuelvo a explicar el uso de una pila (Stack), pues ya lo expliqué en el código 22 - Saber si una cadena tiene paréntesis balanceados

Voy a ilustrarles, de cierta manera, el funcionamiento del algoritmo:

Supongamos que la entrada es:

Código (csharp) [Seleccionar]
string[] expresion = { "4", "2", "10", "+", "*", "5", "-"};

Luego:








EntradaOperaciónPilaComentario
4Introducir en la pila4
2Introducir en la pila4, 2
10Introducir en la pila4, 2, 10
+Suma4, 12Toma los dos últimos valores de la pila (2, 10) y los sustituye por el resultado (12)
*Multiplicación48Toma los dos últimos valores de la pila (4, 12) y los sustituye por el resultado (48)
5Introducir en la pila48 5
-Resta43Toma los dos últimos valores de la pila (48, 5) y los sustituye por el resultado (43)

Al finalizar, el resultado (en este caso 43) será el único elemento en la pila.

Espero que hayan entendido este código.

Salu2s
#334
¿A que te refieres con convertirlo a texto?

Salu2s
#335
ASM / Re: ayuda plis en ensamblador
17 Julio 2015, 17:21 PM
Hola, el título debe ser descriptivo con respecto a tu problema.

También te quería decir que aquí no se hacen tareas y/o resuelven ejercicios, deberías intentar hacerlo y plantear las dudas puntuales que tengas. Estaremos más que dispuesto a ayudarte

Salu2s
#336
¿Podrías poner una imagen de que es lo que pasa cuando redimensionas el navegador?

Salu2s
#337
Las variables i, sum y sum2 tienes que inicializarlas dentro del while para que tengan su valor inicial por cada caso de prueba




Ahora, por la composición del problema, esto parece sacado de un juez en linea, por lo tanto, la manera de leer los datos no creo que sea la correcta, pues cuando te dicen:

CitarLa entrada consiste de varios casos de prueba hasta fin de archivo. Cada caso de prueba consiste en un número entero <= 1000.

No significa que hayan 1000 casos de prueba, sino que van a haber varios casos de prueba donde cada número que te entren va a ser menor o igual a 1000. Por lo tanto tu tienes que ir leyendo hasta el final del archivo los números e ir mostrando el resultado. Algo así como:

MIENTRAS NO FINAL DEL ARCHIVO
HACER
  INICIALIZAR VARIABLES
  LEER NUMERO
  REALIZAR LAS OPERACIONES
  DAR RESULTADO
FIN MIENTRAS


Espero que entiendas.

Salu2s
#338
Cita de: Senior++ en 16 Julio 2015, 17:21 PM
Muchos hijos dicen que por sus padres darían todo... ¿tu estaría dispuesto a dar un ORGANO a tu padre para salvarle la vida y que pueda durar muchos años mas? incluso darle la vida? sean sinceros...

Esta pregunta me surgio por que vi varios Twits diciendo que Nadie da la vida por nadie, y quiero saber...  :P


Yo creo que si lo daría, los padres son algo sagrado, imagina que sin ellos tu no existieras. Hace poco leí algo que me dejo pensando en que a veces no somos lo suficientemente buenos con ellos como deberíamos, o no lo demostramos, la linea decía así:

"Hijo, no te rías cuando no se utilizar el ordenador y te pido que me enseñes, recuerda que yo te enseñe a usar una cuchara"

No obstante, la cuestión creo que sería que tu padre/madre te permita dar un órgano por el/ella. Pues siendo padres, tienen el instinto natural de proteger a sus hijos, y creo que muchos no estarían de acuerdo con que su hijo se sacrificara de esa manera por ellos

Salu2s




@VBSH, estás haciendo doble post! Te recomiendo leer las reglas del foro:

foro.elhacker.net/reglas.htm
#339
Cita de: nito-quie en 16 Julio 2015, 10:36 AM
estoy empezando con la programacion y queria saber las diferencias entre
visual studio 2003. 2005. 2008. 2010 y 2012

Las diferencias son muchas, imagina cuanto puede cambiar un IDE en tantos años. Además, no solo el IDE, sino también los lenguajes, extensiones. Y sobre todo el Framework.

Nota: Te faltó el 2013 y 2015.

Salu2s
#340
Cita de: Orubatosu en 15 Julio 2015, 19:00 PM
Antiguamente también las conexiones eran con modem de 56K

Todavía esto existe aunque no en gran escala.

Por otro lado, todo esto depende de los diseñadores y/o creadores del sitio y sus "necesidades", pues para atraer a más visitantes pueden llegar a hacer de las páginas casi cualquier cosa, esto puede implicar mayor tamaño.

Salu2s