Tracks
/
C#
C#
/
Ejercicios
/
Telemetría hiperoptimizada
Telemetría hiperoptimizada

Telemetría hiperoptimizada

Ejercicio de aprendizaje

Introducción

Números enteros

C#, al igual que muchos lenguajes de tipado estático, ofrece varios tipos que representan números enteros, cada uno con su propio rango de valores. En el extremo inferior, el tipo sbyte tiene un valor mínimo de -128 y un valor máximo de 127. Como en todos los tipos enteros, estos valores están disponibles como <type>.MinValue y <type>.MaxValue. En el extremo superior, el tipo long tiene un valor mínimo de -9,223,372,036,854,775,808 y un valor máximo de 9,223,372,036,854,775,807. Entre ambos se encuentran los tipos short e int.

Los rangos están determinados por el ancho de almacenamiento que el sistema asigna a cada tipo. Por ejemplo, un byte usa 8 bits y un long usa 64 bits.

Cada uno de los tipos anteriores tiene su equivalente sin signo: sbyte/byte, short/ushort, int/uint y long/ulong. En todos los casos, el rango de valores va de 0 al máximo negativo con signo multiplicado por 2 más 1.

Tipo Ancho Mínimo Máximo
sbyte 8 bit -128 +127
short 16 bit -32_768 +32_767
int 32 bit -2_147_483_648 +2_147_483_647
long 64 bit -9_223_372_036_854_775_808 +9_223_372_036_854_775_807
byte 8 bit 0 +255
ushort 16 bit 0 +65_535
uint 32 bit 0 +4_294_967_295
ulong 64 bit 0 +18_446_744_073_709_551_615

Una variable (o expresión) de un tipo se puede convertir fácilmente a otro. Por ejemplo, en una operación de asignación, si el tipo del valor que se asigna (lhs) garantiza que el valor estará dentro del rango del tipo al que se asigna (rhs), entonces hay una asignación simple:

uint ui = uint.MaxValue;
ulong ul = ui;    // no problem

Por otro lado, si el rango del tipo desde el que se asigna no es un subconjunto del rango de valores del tipo de destino, entonces se requiere una conversión explícita mediante (), incluso si el valor concreto está dentro del rango del tipo de destino:

short s = 42;
uint ui = (uint)s;

Conversión de bits

La clase BitConverter ofrece una forma práctica de convertir tipos enteros desde y hacia array de bytes.

Instrucciones

El proyecto del carro de control remoto continúa. El ancho de banda del sistema de telemetría es muy limitado, así que te han pedido implementar un protocolo de mensajes para comunicar los datos de telemetría.

Los datos se transmiten en un búfer (array de bytes). Cuando se envían números enteros, el tamaño del búfer se reduce empleando el protocolo que se describe a continuación.

Cada valor debe representarse con el tipo entero más pequeño posible (los tipos byte y sbyte no se incluyen, ya que el ahorro sería insignificante):

De A Tipo
4_294_967_296 9_223_372_036_854_775_807 long
2_147_483_648 4_294_967_295 uint
65_536 2_147_483_647 int
0 65_535 ushort
-32_768 -1 short
-2_147_483_648 -32_769 int
-9_223_372_036_854_775_808 -2_147_483_649 long

El valor debe convertirse a la cantidad de bytes apropiada para el tipo que se le asigne. El búfer completo se compone de un byte que indica la cantidad de bytes adicionales en el búfer (byte de prefijo) seguido de los bytes que contienen el número entero (bytes de carga útil).

Algunos de los tipos usan una cantidad idéntica de bytes (por ejemplo, los tipos uint e int). Normalmente tendrían el mismo byte de prefijo, pero eso haría que la decodificación fuera problemática. Para contrarrestarlo, el protocolo introduce un pequeño truco: en los tipos con signo, el valor de su byte de prefijo es 256 menos la cantidad de bytes adicionales en el búfer.

En la comunicación solo se enviarán el byte de prefijo y la cantidad de bytes siguientes que este indique. De forma interna se usa un búfer de 9 bytes (con ceros al final, según sea necesario), tanto en las rutinas de envío como en las de recepción.

1. Codifica un valor entero listo para enviar

Implementa el método estático TelemetryBuffer.ToBuffer() para codificar un búfer tomando el parámetro que se le pasa al método.

// Type: ushort, bytes: 2, signed: no, prefix byte: 2
TelemetryBuffer.ToBuffer(5)
// => {0x2, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

// Type: int, bytes: 4, signed: yes, prefix byte: 256 - 4
TelemetryBuffer.ToBuffer(Int32.MaxValue)
// => {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 };

2. Decodifica un búfer recibido

Implementa el método estático TelemetryBuffer.FromBuffer() para decodificar el búfer recibido y devolver el valor en forma de long.

TelemetryBuffer.FromBuffer(new byte[] {0xfc, 0xff, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x0, 0x0 })
// => 2147483647

Si el byte de prefijo tiene un valor inesperado, se debe devolver 0.

Editar en GitHub El enlace se abre en una ventana o una pestaña nuevas
C# Exercism

¿Todo listo para empezar Telemetría hiperoptimizada?

Regístrate en Exercism para aprender y dominar C# con 62 conceptos178 ejercicios y mentoría humana real, todo gratis.