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

Telemetría hiperoptimizada

Ejercicio de aprendizaje

Introducción

Números enteros

C#, como muchos lenguajes de tipado estático, proporciona una serie de 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 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 ellos se encuentran los tipos short e int.

Los rangos están determinados por el ancho de almacenamiento del tipo tal como lo asigna el sistema. Por ejemplo, un byte utiliza 8 bits y un long utiliza 64 bits.

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

Tipo Ancho Mínimo Máximo
sbyte 8 bits -128 +127
short 16 bits -32_768 +32_767
int 32 bits -2_147_483_648 +2_147_483_647
long 64 bits -9_223_372_036_854_775_808 +9_223_372_036_854_775_807
byte 8 bits 0 +255
ushort 16 bits 0 +65_535
uint 32 bits 0 +4_294_967_295
ulong 64 bits 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 (el de la izquierda) garantiza que el valor estará dentro del rango del tipo al que se asigna (el de la derecha), entonces se trata de 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 al que se asigna, entonces se requiere una conversión de tipo (cast), la operación (), incluso si el valor concreto está dentro del rango del tipo al que se asigna:

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

Conversión de bits

La clase BitConverter proporciona una forma cómoda de convertir tipos enteros a y desde arrays de bytes.

Instrucciones

El trabajo en el proyecto del coche teledirigido continúa. El ancho de banda del sistema de telemetría escasea y se te ha pedido que implementes un protocolo de mensajes para comunicar los datos de telemetría.

Los datos se transmiten en un búfer (una matriz 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 en 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 al número de bytes adecuado para el tipo que se le asigne. El búfer completo consta de un byte que indica el número de bytes adicionales que hay 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 el mismo número 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 el número de bytes adicionales que hay en el búfer.

En la comunicación solo se enviarán el byte de prefijo y el número de bytes siguientes indicado por el prefijo. De forma interna, tanto las rutinas de envío como las de recepción usan un búfer de 9 bytes (con ceros finales, según sea necesario).

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 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, debe devolverse 0.

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

¿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.