Parrots Yanee es una entusiasta de las aves. Desde que ha comenzado a leer acerca de IP o Aves ras (IPoAM), ella ha pasado una buena parte de su tiempo entrenando una flota de aves inteligentes para llevar mensajes a través de largas distancias. El sueño de Yanee es utilizar sus aves para enviar un mensaje M a una tierra muy lejana. Su mensaje M es una secuencia de N enteros (no necesariamente distintos), cada uno de ellos entre 0 y 255 inclusive. Yanee tiene K aves especialmente entrenados. Todas las aves se ven iguales; Yanee no les puede decir que se separen. Cada ave puede recordar un entero entre 0 y R inclusive. Anteriormente, ella trató de utilizar el siguiente esquema: para enviar un mensaje, Yanee debe dejar salir cuidadosamente las aves una por una de su jaula. Antes de que cada ave sea enviada al aire, ella le enseñó a cada ave un número del mensaje en orden. Desafortunadamente, dicho sistema no funcionó. Eventualmente, todas las aves llegaron a su destino, pero no necesariamente en el orden que fueron enviadas. Con este esquema, Yanee puede recuperar de las aves todos los números que envió, pero es incapaz de colocarlos en el orden correcto del mensaje original. Para cumplir su sueño, Yanee va a necesitar un mejor planteamiento, y es para ello que ella necesita su ayuda. Dado un mensaje M, ella planea liberar a las aves una por una como fue anteriormente. Ella necesita que usted escriba un programa que sea capaz de cumplir con dos (2) operaciones: Primero, su programa debe ser capaz de leer un mensaje M y transformarlo en una secuencia de a lo sumo K enteros entre 0 y R que ella le enseñará a las aves. Segundo, su programa debe ser capaz de leer una lista de enteros entre 0 y R en el orden en que las aves llegan a su destino, y luego transformarla de nuevo en el mensaje original M. Usted puede asumir que todas las aves siempre llegan a su destino, y cada una de ellas recuerda el número que se le asignó. Yanee le recuerda de nuevo que las aves pueden llegar en cualquier orden. Note que Yanee tiene solo K aves, esto significa que la secuencia de enteros entre 0 y R que usted debe producir puede contener a lo sumo K enteros. Problema Ecriba dos procedimientos separados. Uno de ellos será utilizado por el emisor (codificador) y el otro por el receptor (decodificador). El proceso general se explica en la siguiente figura: Original Codificado Mezclado de Salida Codificador Mezclador Decodificador Debe ser igual a M Los dos procedimientos que usted debe escribir son: Page 1 of 7
Procedimiento encode(n,m) que recibe los siguientes parámetros: N: el tamaño del mensaje original M: un arreglo unidimensional con N enterso representando el mensaje. Usted puede asumir que 0 M[i] 255 for 0 i < N. Este procedimiento debe codificar el mensaje M en una secuencia de enteros entre 0 y R inclusive, que debe ser enviado utilizando las aves. Para entregar la secuencia de salida, su procedimiento encode debe llamar al procedimiento send(a) para cada entero a que usted desee entregar a una de las aves. Procedimento decode(n,l,x) que toma los siguientes parámetros: N: el tamaño del mensaje original L: el tamaño del mensaje recibido (el número de aves que fueron enviadas). X: un arreglo unidimensional de L enteros representando los números recibidos. Los números X[i] para 0 i < L son exactamente los números que su procedimiento encode produce, pero posiblemente no estén en el mismo orden. Dicho procedimiento debe recuperar el mensaje original. Para entregar dicho mensaje, su procedimiento debe llamar al procedimiento output(b) para cada entero b en el mensaje decodificado, en el orden correcto. Note que R y K no son dados como parámetros de entrada (por favor lea las descripciones de las subtareas más abajo) Para solucionar correctamente una subtarea, su procedimiento debe satisfacer las siguientes condiciones: Todos los enteros enviados por su procedimiento encode deben encontrarse en el rango especificado en la subtarea. El número de veces que su procedimiento encode llama al procedimiento send no debe exceeder el límite K especificado en la subtarea. Por favor note que K depende de la longitud del mensaje. El procedimiento decode debe recuperar de forma correcta el mensaje original M y llamar al procedimiento output(b) exactamente N veces, con b igual a M[0], M[1],..., M[N-1], respectivamente En la última subtarea, su puntuación varía de acuerdo a la tasa entre las longitudes del mensaje codificado y el mensaje original. Page 2 of 7
Ejemplo Considere el caso con N = 3, y M= 10 30 20 Procedimiento encode(n,m) utilizando algún método mágico, puede codificar el mensaje como una secuencia de números (7, 3, 2, 70, 15, 20, 3). Para entregar esta secuencia, debe llamar al procedimiento send como se muestra a continuación: send(7) send(3) send(2) send(70) send(15) send(20) send(3) Debido a que todas las aves llegan a su destino, asuma que obtenemos la siguiente lista de números: (3, 20, 70, 15, 2, 3, 7). El procedimiento decode será invocado con N=3, L=7, y X= 3 20 70 15 2 3 7 El procedimiento decode debe producer el mensaje original (10, 30, 20). Y reportar su resultado invocando el procedimiento output como sigue. output(10) output(30) output(20) Subtareas Subtarea 1 (17 puntos) N = 8, y cada entero en el arreglo M es cero (0) o uno (1) Page 3 of 7
Cada entero codificado debe estar en el rango de 0 a R=65535 inclusive. El número de veces que usted puede llamar el procedimiento send es a lo sumo K=10 N. Subtarea 2 (17 puntos) 1 N 16. Cada entero codificado debe estar en el rango de 0 a R=65535 inclusive. El número de veces que usted puede invocar el procedimiento send es a lo sumo K=10 N. Subtarea 3 (18 puntos) 1 N 16. Cada entero codificado debe estar en el rango de 0 a R=255 inclusive. El número de veces que usted puede invocar el procedimiento send es a lo sumo K=10 N. Subtarea 4 (29 puntos) 1 N 32. Cada entero codificado debe estar en el rango de 0 a R=255 inclusive. El número de veces que usted puede invocar el procedimiento send es a lo sumo K=10 N. Subtarea 5 (hasta 19 puntos) 16 N 64. Cada entero codificado debe estar en el rango desde 0 a R=255 inclusive. El número de veces que usted puede llamar al procedimiento send es a lo sumo K=15 N. Importante: el resultado de dicha subtarea depende de la proporción entre la longitud del mensaje codificado y el mensaje original Para un caso de prueba t en esta subtarea, sea Pt=Lt/Nt la proporción entre la longitud Lt del mensaje codificado y la longitud Nt del mensaje original. Sea P el máximo de todos los Pt. Su puntuación para esta subtarea será determinada utilizando las siguientes reglas: Si P 5, usted obtendrá la puntuación completa, 19 puntos. Si 5 < P 6, usted obtendrá 18 puntos. Si 6 < P 7, usted obtendrá 17 puntos. Si 7 < P 15, usted obtendrá 1 + 2 (15 - P), redondeando hacia abajo al entero más cercano. Si P > 15 o cualquiera de sus salidas es incorrectas, su puntuación es 0. Importante: cualquier solución válida para las subtareas de la 1 a la 4 también debe solucionar las subtareas precedentes. Sin embargo, dado que K tiene un límite mayor, una solución válida para la subtarea 5 pudiera no ser capaz de solucionar las subtareas de la 1 a la 4. No obstante es posible solucionar todas las subtareas utilizando la misma solución. Page 4 of 7
Page 5 of 7
Detalles de Implementación Límites Entorno de evaluación (Grading Environment): en el entorno de evaluación real, sus soluciones serán compiladas en 2 programas e y d para ser ejecutadas por separado. Ambos módulos encoder y decoder serán enlazados para cada ejecutable, pero e sólo invocará a encode y d sólo invocará a decode. Tiempo límite de CPU (CPU time limit): el programa e realizará 50 llamadas al procedimiento encode y debe finalizar antes de 2 segundos. El programa d realizará 50 llamadas al procedimiento decode y debe finalizar antes de 2 segundos. Límite de memoria (Memory limit): 256 MB Nota: no existe un límite explícito para el tamaño de la pila. Dicha memoria cuenta dentro del total de memoria utilizado. Interfaz (API) Directorio de implementación: parrots/ Para ser implementado por el participante: encoder.c o encoder.cpp o encoder.pas decoder.c o decoder.cpp o decoder.pas Nota para los programadores en C/C++: tanto en el grader ejemplo como en el real, encoder.c[pp] y decoder.c[pp] serán enlazadas juntas en el grader. Por ende, usted debe declarar todas las variables globales como estáticas (static) dentro de cada archivo para prevenir interferencias con variables de otros archivos. Contestant interface: encoder.h or encoder.pas decoder.h or decoder.pas Grader interface: encoderlib.h or encoderlib.pas decoderlib.h or decoderlib.pas Sample grader: grader.c or grader.cpp or grader.pas El grader ejemplo se ejecutará dos veces. En la primera ronda, realiza una llamada a encode con la data inicial, y luego llama a decode con la salida producida por encode. En dicha ronda el grader no realiza ningún cambio en el orden de los enteros en el mensaje codificado. En la segunda ronda el grader intercambia los enteros en posiciones pares e impares. El grader real implementa varios tipos de permutaciones a los mensajes codificados. Usted puede cambiar la forma en que el grader ejemplo permuta los datos modificando el procedimiento shuffle (en C/C++). El grader de ejemplo además chequea rango y longitude de los datos codificados. Por defecto, chequea que la data codificada esté en el rango 0 y 65535 inclusive, y que la longitud es a lo sumo 10 N. Usted puede cambiar estos parámetros modificando las constantes channel_range (desde 65535 a 255, por ejemplo) y max_expansion (a 10 15 o 7 Page 6 of 7
por ejemplo). Entrada ejemplo para el grader: grader.in.1, grader.in.2,... Nota: el grader ejemplo lee la entrada en el format siguiente: Línea 1: N Línea 2: a list of N numbers: M[0], M[1],..., M[N-1] Salida esperada por el grader: grader.expect.1, grader.expect.2,... Para ésta tarea, cada uno de estos archives debe contener exactamente el texto Correct. Page 7 of 7