Archivo

Entradas Etiquetadas ‘xor’

Recopilación de soluciones para los retos de #tuentiContest . Challenge #19

Jueves, 30 de Junio de 2011 Gaspar Fernández Sin comentarios

Últimamente he hablado acerca del I concurso de programación de Tuenti. Un concurso de programación Online que se llevó acabo durante la semana pasada (del 13 al 20 de Junio, muy mala fecha).

Podéis ver los enunciados de todos los problemas, con ejemplos sobre la entrada y salida (aunque a veces no hay que hacerles mucho caso) en la web oficial del concurso, pero en Vidas Concurrentes lo encontramos todo en español.

Challenge #19 : The Caesar Salad

Un mensaje cifrado con 4 métodos distintos, todo acompañado de una adivinanza
Soluciones:

Si no estás en la lista y quieres plantear tu solución, deja un comentario con tu link !

Actualización 2011/07/03 01:49 : Añadida solución de @frisco82
Actualización 2011/07/03 13:52 : Añadida solución de @Rosapolis

Bailando con bits: Trabajando a nivel de bit II

Miércoles, 23 de Junio de 2010 Gaspar Fernández Sin comentarios

Hace unos días empecé con la serie Bailando con Bits (aunque llevaba escrito varios meses) trata de formas para trabajar a nivel de bit desde C.

Hoy voy a proponer otra forma, quizás menos intuitiva que la anterior, pero diferente. Esta vez no utilizaremos un registro enorme ni nada parecido, utilizaremos un mismo número entero para hacer el ejemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>

#define PESOBIT(bpos) 1<<bpos
#define COGEBIT(var,bpos) (var & PESOBIT(bpos))?1:0
#define PONE_1(var,bpos) var | PESOBIT(bpos)
#define PONE_0(var,bpos) var & ~(PESOBIT(bpos))
#define CAMBIA(var,bpos) var ^ PESOBIT(bpos)

int main()
{
  int numero;
  int i;

  numero=63;
  printf ("Numero: %d\n", numero);


  for (i=31; i>=0; i--)
    printf("%4d", i);

  printf("\n");

  for (i=31; i>=0; i--)
    printf("%4d",COGEBIT(numero,i));

  printf("\n");

  numero=PONE_1(numero, 17);
  numero=PONE_0(numero, 3);
  numero=CAMBIA(numero, 20);
  numero=CAMBIA(numero, 5);

  for (i=31; i>=0; i--)
    printf("%4d",COGEBIT(numero,i));

  printf("\nNúmero: %d\n", numero);

}

Ahora usamos varias macros que harán operaciones de bit con la variable a analizar (están definidas en la parte de arriba), tenemos PESOBIT, COGEBIT, PONE_1, PONE_0 y CAMBIA:

  • PESOBIT: Nos dice cuánto vale un bit con valor 1 en la posición especificada, por ejemplo en la posición 0 (LSB) vale 1, en la posición 1, vale 2, en la posición 3, vale 4, en la posición 4, vale 8…
  • COGEBIT: Nos dice si el bit en la posición bpos de la variable var vale 0 ó 1
  • PONE_1: Pone un 1 en el bit bpos de la variable var
  • PONE_0: Pone un 0 en el bit bpos de la variable var
  • CAMBIA: Cambia el valor (de 0 a 1 y viceversa) del bit en la posición bpos de la variable var

Como vemos en el ejemplo si queremos poner a 1 el bit 5 de numero, tendremos que hacer numero=PONE_1(numero,5), aunque en el siguiente ejemplo veremos cómo simplificar todo eso.

Con este ejemplo podemos jugar con los bits de números enteros. Pero, y si queremos utilizar otro tipo de variables? (aunque estamos limitados a 32bits) También tenemos este ejemplo con un tipo float:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>

#define PESOBIT(bpos) 1<<bpos
#define COGEBIT(var,bpos) (*(unsigned*)&var & PESOBIT(bpos))?1:0
#define PONE_1(var,bpos) *(unsigned*)&var |= PESOBIT(bpos)
#define PONE_0(var,bpos) *(unsigned*)&var &= ~(PESOBIT(bpos))
#define CAMBIA(var,bpos) *(unsigned*)&var ^= PESOBIT(bpos)

int main()
{
  float numero;

  int i;

  numero=63.2317;
  printf ("Numero: %f\n", numero);


  for (i=31; i>=0; i--)
    printf("%4d", i);

  printf("\n");

  for (i=31; i>=0; i--)
    printf("%4d",COGEBIT(numero,i));

  printf("\n");

  PONE_1(numero, 5);
  PONE_0(numero, 3);
  CAMBIA(numero, 20);
  CAMBIA(numero, 5);
  CAMBIA(numero, 31);

  for (i=31; i>=0; i--)
    printf("%4d",COGEBIT(numero,i));

  printf("\n");

  printf("\nNúmero: %f\n", numero);

}

En este caso no tenemos que hacer una variable igual a PONE_1(variable, 5) para poner su bit a 1; simplemente con PONE_1(variable, 5) nos vale. En este ejemplo podemos ver una variable de tipo float desglosada en bits y podemos modificar a nivel de bit para obtener otros valores. (No le veo mucha utilidad a esto, pero bueno).

Post dedicado a algm, por su comentario en el artículo Bailando con bits anterior.

Decimal a Binario (y negativos en Complemento a 2)

Martes, 2 de Junio de 2009 Gaspar Fernández 4 comentarios

Aquí traigo un fragmento de código que nos puede ayudar bastante a la hora de hacer cambios de base de decimal a binario, sobre todo porque para manejarnos con los números negativos utilizamos el Complemento a dos.

En principio, antes de hacer esta función miré un poco el blog Static Zero, y luego me decidí simplificar un poco el código. Así ha quedado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
int *decToBin(int decimal, int nBits, int binary[]) {
    int i;

    int flag = 0;
    /* Si es un número negativo, lo hacemos positivo y le restamos 1(*), */
    /* además activamos el flag para saber que es negativo */

    /* (*) El complemento a 2 es igual que el complemento a 1, que es cambiar */
    /* 1->0, 0->1, y luego sumando 1 en binario. Aquí restamos 1 en decimal y */
    /* luego pasamos a binario. */
    if (decimal < 0)
        {
            flag = 1;
            decimal = -decimal-1;
        }

    /* Pasamos a binario, atendiendo a lo que vale flag, en lugar de añadir (decimal%2) */
    /* como es normal, le hacemos un XOR con flag, vemos la tabla de verdad de XOR */
    /* |    A    (xor)   B       =   X   |  */
    /* |     0      |        0       |   0   |  */
    /* |     0      |        1       |   1   |  */
    /* |     1      |        0       |   1   |  */
    /* |     1      |        1       |   0   |  */
    /* ------------------------------   */
    /* Por tanto, cuando flag vale 0, al encontrar un 0, pondremos un 0, y al encontrar un 1, ponemos un 1 */
    /*           Pero cuando flag vale 1, al encontrar un 0, pondremos un 1, y al encontrar un 1, ponemos un 0 */
    while (decimal > 0)
        {
            binary[--nBits] = flag^(decimal%2);
            decimal/=2;
        }

    /* Con esto terminamos de llenar el array, con 0 a la izquierda si es un número positivo */
    /* y con 1s si es un número negativo */
    while (nBits>0)
        binary[--nBits] = flag;
   
    /* Devolvemos el array */
    return binary;
}

Para descargar este código y un pequeño programa de prueba:
Pasar de decimal a binario (Negativos en complemento a 2)

Visita otras webs de la red