Tablas de búsqueda

  1. Defina el tipo enumerativo mes_t con 12 símbolos, uno por cada mes. Escriba una porción de código que dada una variable de tipo mes_t, imprima por pantalla el mes correspondiente.

  2. La clasificación espectral [1] de estrellas (cuerpos celestes) permite agruparlas en función de su temperatura, como se muestra en la tabla siguiente

    Clase

    Temperatura

    Color

    O

    28000 - 50000 K

    Azul

    B

    9600 - 28000 K

    Blanco azulado

    A

    7100 - 9600 K

    Blanco

    F

    5700 - 7100 K

    Blanco amarillento

    G

    4600 - 5700 K

    Amarillo

    K

    3200 - 4600 K

    Naranja

    M

    1700 - 3200 K

    Rojo

    1. Defina el tipo enumerativo espectral_t con los símbolos correspondientes a las clases espectrales.

    2. Escriba un programa que le pida al usuario la temperatura de un cuerpo celeste y almacene la clase del mismo en una variable del tipo espectral_t. Luego, imprima el color de la estrella.

  3. El autopiloto de un vehículo aéreo autónomo (UAV) soporta la comunicación con una computadora externa a través de un puerto serie que admite las siguientes velocidades [2]: 9600, 19200, 34800, 57600, 115200, 230400, 460800, 500000 y 921600, en Baudios (baudrate).

    1. Definir un tipo enumerativo que contenga dichos valores.

    2. Escribir una porción de código en la que, en función de un entero que almacena un valor de baudrate, se almacene un valor adecuado en una variable del tipo enumerativo definido anteriormente.

    3. Compare su implementación con el código del autopiloto en el repositorio oficial

  4. Un número de CUIT es un número de 2 + 8 + 1 = 11 dígitos, donde los primeros dos dígitos hasta el año 2021 correspondían al tipo, siendo 20 hombre, 27 mujer y 24 para repetidos, los 8 al número de DNI y el último dígito un dígito verificador.

    El dígito verificador se calcula como una suma ponderada de los otros 10 dígitos, por ejemplo, si el tipo es mujer y el DNI es 12345678 se computa:

    \(\underline2\times5 + \underline7\times4 + \underline1\times3 + \underline2\times2 + \underline3\times7 + \underline4\times6 + \underline5\times5 + \underline6\times4 + \underline7\times3 + \underline8\times2 = 176.\)

    Se calcula el resto de dividir ese número por 11 (en este caso es 0). Si el resto es 0 el dígito verificador es 0. Si el resto es mayor a 1 el dígito verificador es 11 - resto. En el caso de que el resto sea 1 entonces el tipo se cambia por 23 y el dígito queda 9 si el tipo era hombre, 4 si el tipo era mujer y 3 si el tipo era repetido. En el ejemplo la CUIT resultante es 27123456780.

    Implementar una función uint64_t generar_cuit(tipo_t tipo, int dni); que dado el enumerativo tipo y el dni genere la CUIT correspondiente.

  5. La máquina Enigma era un dispositivo mecánico utilizado por los nazis para cifrar mensajes durante la Segunda Guerra Mundial. La misma consistía en una serie de rotores con 26 posiciones, tantas como las letras del abecedario, que asignaban a cada posición de entrada una posición de salida. Entre un lado y el otro del rotor había una cable que vinculaba entrada con salida.

    Por ejemplo, este es un esquema del Rotor I de la máquina Enigma I:

    ../_images/enigma.png

    donde si uno entra por la letra A de la derecha saldrá por la E de la izquierda y viceversa.

    La máquina consistía en tres rotores y un reflector, donde la señal entraba desde el rotor de la derecha, pasaba al del medio, al de la izquierda y luego al reflector donde volvía en el sentido inverso. En este artículo de Wikipedia puede verse un esquema más completo así como la lista y cableado de cada uno de los rotores.

    El Rotor I puede representarse en un vector como:

    uint8_t rotor_i[26] = {4, 10, 12, 5, 11, 6, 3, 16, 21, 25, 13, 19, 14, 22, 24, 7, 23, 20, 18, 15, 0, 8, 1, 17, 2, 9};
    

    donde cada una de las posiciones del vector se corresponden a las letras de la 'A' a la 'Z' y el valor asociado se corresponde con la posición de salida entrando de derecha a izquierda. Por ejemplo, para la entrada 'A' la salida será 'E' dado que rotor_i[0] == 4, o traduciendo posiciones en letras rotor_i['A'] == 'E'.

    Ahora bien, los rotores pueden girar (¡y giran!) y estar en cualquier posición, el ejemplo anterior fue para el rotor puesto en la posición 'A', es decir, en la posición inicial. Si el rotor estuviera, en la posición 'B', es decir rotado una posición, entonces todos los valores se desplazarían. Por ejemplo, ahora la 'A' se traduciría como 'J'. Para llegar a este resultado hay que ver que rotor_i['B'] == 'K', como todo el rotor está rotado una unidad entonces la 'A' entra en la posición de la 'B' y luego la 'K' se traduce como 'J'.

    Implementar:

    1. Una función char codificar_dai_a(uint8_t rotor[], char caracter); que codifique el caracter recorriendo el rotor, en su posición inicial ('A') de derecha a izquierda. Por ejemplo, codificar_dai_a(rotor_i, 'A') -> 'E'.

    2. Una función char codificar_iad_a(uint8_t rotor[], char caracter); que codifique el caracter pero de izquierda a derecha. Ejemplo, codificar_iad_a(rotor_i, 'E') -> 'A'.

    3. Una función char codificar_dai(uint8_t rotor[], char posicion, char caracter); que codifique el caracter recorriendo el rotor en esa posicion de derecha a izquierda. Por ejemplo, codificar_dai(rotor_i, 'B', 'A') -> 'J'.

      Notar que codificar_dai(rotor, 'A', caracter) == codificar_dai_a(rotor, caracter).

    4. Una función char codificar_iad(uint8_t rotor[], char posicion, char caracter); que realice la codificación de izquierda a derecha. Por ejemplo, codificar_iad(rotor_i, 'B', 'J') -> 'A'.

    5. Si tenés ganas de implementar la máquina completa en la misma tenés tres rotores, cada uno con su posición inicial y un reflector. Cada vez que se codifica una letra del mensaje se recorren los tres discos de derecha a izquierda y viceversa y además se rota en una unidad el rotor de la derecha, cuando el rotor de la derecha completara una vuelta se rotará una unidad el rotor del medio y cuando este completara una vuelta se rotará una unidad el de la izquierda (esto último es una simplificación, acá pueden verse las posiciones de cada rotor que disparan el giro del rotor de la izquierda).

    Se proveen los otros rotores así como los reflectores de la Enigma I:

    uint8_t rotor_ii = {0, 9, 3, 10, 18, 8, 17, 20, 23, 1, 11, 7, 22, 19, 12, 2, 16, 6, 25, 13, 15, 24, 5, 21, 14, 4};
    uint8_t rotor_iii = {1, 3, 5, 7, 9, 11, 2, 15, 17, 19, 23, 21, 25, 13, 24, 4, 8, 22, 6, 0, 10, 12, 20, 18, 16, 14};
    uint8_t rotor_iv = {4, 18, 14, 21, 15, 25, 9, 0, 24, 16, 20, 8, 17, 7, 23, 11, 13, 5, 19, 6, 10, 3, 2, 12, 22, 1};
    uint8_t rotor_v = {21, 25, 1, 17, 6, 8, 19, 24, 20, 15, 18, 3, 13, 7, 11, 23, 0, 22, 12, 9, 16, 14, 5, 4, 2, 10};
    uint8_t rotor_vi = {9, 15, 6, 21, 14, 20, 12, 5, 24, 16, 1, 4, 13, 7, 25, 17, 3, 10, 0, 18, 23, 11, 8, 2, 19, 22};
    uint8_t rotor_vii = {13, 25, 9, 7, 6, 17, 2, 23, 12, 24, 18, 22, 1, 14, 20, 5, 0, 8, 21, 11, 15, 4, 10, 16, 3, 19};
    uint8_t rotor_viii = {5, 10, 16, 7, 19, 11, 23, 14, 2, 1, 9, 18, 15, 3, 25, 17, 0, 12, 4, 22, 13, 8, 20, 24, 6, 21};
    uint8_t reflector_a = {4, 9, 12, 25, 0, 11, 24, 23, 21, 1, 22, 5, 2, 17, 16, 20, 14, 13, 19, 18, 15, 8, 10, 7, 6, 3};
    uint8_t reflector_b = {24, 17, 20, 7, 16, 18, 11, 3, 15, 23, 13, 6, 14, 10, 12, 8, 4, 1, 5, 25, 2, 22, 21, 9, 0, 19};
    uint8_t reflector_c = {5, 21, 15, 9, 8, 0, 14, 24, 4, 3, 17, 25, 23, 22, 6, 2, 19, 10, 20, 16, 18, 1, 13, 12, 7, 11};
    

Manejo de bits y tablas

  1. En este ejercicio de la guía de bits se plantea que los bits del factor de división configuran la siguiente tabla:

    SPR1

    SPR0

    Factor de división

    Frecuencia de clock

    0

    0

    2

    1MHz

    0

    1

    4

    500kHz

    1

    0

    16

    125kHz

    1

    1

    32

    62.5kHz

    Se pide escribir una función que devuelva por el nombre el factor de división del clock interno, que responda al prototipo:

    int getPrescalingFactor(uint8_t);
    
  2. En muchas aplicaciones de electrónica es necesario controlar un display de 7 segmentos. En un display de 7 segmentos se tienen terminales que prenden los segmentos y el punto. Cuando un terminal se pone en 1 el segmento correspondiente se ilumina:

    ../_images/7segments.png

    Por ejemplo, para configurar la forma de un 9 se deben prender los terminales 0, 1, 2, 3, 5, 6. Como se trata de 8 valores los mismos se pueden codificar en un byte, siendo este valor el binario 01101111 o el hexadecimal 0x6F.

    Implementar una función uint8_t digito_a_7seg(int digito); que reciba un dígito entre 0 y 15 y devuelva la configuración de segmentos de display necesarios para dibujar los caracteres del 0 al 9 y de la A a la F respectivamente.

  3. Los primeros dispositivos capaces de transmitir texto fueron los teletipos. En 1874 Émile Baudot desarrolló el Baudot Multiplex System el cual transmitía caracteres utilizando un código de 5 bits.

    La tabla ITA1 (International Telegraph Alphabet 1) basada en la tabla de Baudot tenía la siguiente distribución:

    0

    1

    2

    3

    4

    5

    6

    7

    8

    9

    A

    B

    C

    D

    E

    F

    0x0_

    NUL

    A

    E

    CR

    Y

    U

    I

    O

    FIGS

    J

    G

    H

    B

    C

    F

    D

    0x1_

    SP

    LF

    X

    Z

    S

    T

    W

    V

    DEL

    K

    M

    L

    R

    Q

    N

    P

    Siendo NUL equivalente al '\0', CR al '\r', SP al espacio, LF al '\n' y DEL al '\b'.

    El carácter 0x08, FIGS, lo que hace es alternar entre esta tabla y la tabla de figuras que es la que sigue:

    0

    1

    2

    3

    4

    5

    6

    7

    8

    9

    A

    B

    C

    D

    E

    F

    0x0_

    NUL

    1

    2

    CR

    3

    4

    5

    SP

    6

    7

    +

    8

    9

    0

    0x1_

    LTRS

    LF

    ,

    :

    .

    ?

    '

    DEL

    (

    )

    =

    -

    /

    %

    Donde el carácter 0x10, LTRS, vuelve a la tabla anterior. Los caracteres en blanco no están especificados y se dejan disponibles para completar por la administración de cada red.

    (Notar que 0x08 y 0x10 son FIGS y LTRS respectivamente en ambas tablas... si se invoca FIGS en modo FIGS se imprime un espacio y análogamente con LTRS en ese modo.)

    Escribir una función que reciba una cadena en texto Baudot y la convierta en texto ASCII y otra que haga el camino inverso.

  4. En este ejercicio se describieron las tablas de codificación de caracteres Unicode y su representación en formato UTF-8.

    Los codepoints 225, 224, 227, 228 por ejemplo representan a los caracteres á, à, ã y ä respectivamente.

    Se quiere implementar una tabla de búsqueda que sirva para reemplazar caracteres extendidos del Unicode por versiones ASCII, por ejemplo, los cuatro caracteres ya mencionados se reemplazarían por la a.

    1. Escribir una función char codepoint_a_ascii(uint32_t codepoint); que reciba un codepoint Unicode y lo reemplace por el ASCII correspondiente utilizando una tabla de búsqueda. En caso de que el codepoint fuera menor al valor 128, el mismo ya sería un carácter ASCII. Si el codepoint recibido no estuviera en la tabla de búsqueda devolver el carácter '*' (asterisco).

    2. Haciendo uso de las funciones de este ejercicio implementar una función: bool char_to_ascii(const char s[], char ascii[]); que dada una secuencia de caracteres s en codificación UTF-8 convierta a la misma a su versión ASCII reemplazando cada uno de los caracteres extendidos por sus sustitutos. Por ejemplo, dada la cadena "Piñón" debe devolverse "Pinon".

    Obviamente no es la idea generar una tabla con los 2 millones de caracteres Unicode, sino plantear la idea general de resolución del problema con una tabla con un par de valores. En este artículo de Wikipedia se listan los caracteres del segmento que utilizamos en el idioma castellano. Bien puede armarse la tabla con á, é, í, ó, ú, ü, ñ y sus mayúsculas.