Es posible comprimir algunos tipos de datos, como texto humano o código fuente, con gramáticas en línea recta. Básicamente, se crea una gramática cuyo idioma tiene exactamente una palabra: los datos sin comprimir. En esta tarea, debe escribir un programa que implemente este método de competencia de datos.
Entrada
La entrada es una cadena de no más de 65535 bytes de longitud. Se garantiza que la entrada coincide con la expresión regular [!-~]+
(es decir, al menos un carácter ASCII imprimible excluyendo espacios en blanco).
Un ejemplo de entrada es
abcabcbcbcabcacacabcabab
Salida
La salida es un conjunto de reglas que forman una gramática que describe exactamente una palabra (la entrada). Cada no terminal se denota con un número decimal mayor que 9. El símbolo de inicio es el símbolo número diez. A continuación se muestra una salida de ejemplo correspondiente a la entrada de ejemplo; Su sintaxis se describe más adelante:
10=11 11 12 12 11 13 13 11 14 14
11=a 12
12=b c
13=a c
14=a b
Cada regla tiene la forma <nonterminal>=<symbol> <symbol> ...
con un número arbitrario de símbolos separados por espacios en blanco en el lado derecho. Cada salida que obedece las siguientes restricciones y deriva exactamente la cadena de entrada es válida.
Restricciones
Para evitar que las personas hagan cosas extrañas, se están aplicando varias restricciones:
Cada no terminal debe aparecer al menos dos veces en el lado derecho de una regla. Por ejemplo, la siguiente gramática para la entrada
abcabc
es ilegal porque la regla 12 aparece solo una vez:10=12 11=a b c 12=11 11
Ninguna secuencia de dos símbolos adyacentes puede aparecer más de una vez en todos los lados derechos de todas las reglas, excepto si se superponen. Por ejemplo, la siguiente gramática para la entrada
abcabcbc
es ilegal ya que la secuenciabc
aparece dos veces:10=11 11 b c 11=a b c
Una gramática válida sería:
10=11 11 12 11=a 12 12=b c
Su programa debe finalizar en menos de un minuto por cada entrada válida que no supere los 65535 bytes.
Como de costumbre, no puede utilizar ninguna instalación de su idioma ni ninguna función de biblioteca que haga que la solución sea trivial o que implemente una gran parte de ella.
Entrada de muestra
Genere una entrada de muestra con el siguiente programa en C.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
unsigned int i,j = 0,k;
if (argc != 3
|| 2 != sscanf(argv[1],"%u",&i)
+ sscanf(argv[2],"%u",&k)) {
fprintf(stderr,"Usage: %s seed length\n",argv[0]);
return EXIT_FAILURE;
}
srand(i);
while(j < k) {
i = rand() & 0x7f;
if (i > 34 && i != 127) j++, putchar(i);
}
return EXIT_SUCCESS;
}
La entrada de muestra generada por el programa anterior generalmente no dará como resultado buenos resultados de compresión. Considere utilizar texto humano o código fuente como entrada de ejemplo.
Criterios ganadores
Este es el código de golf; el programa con el código fuente más corto gana. Para obtener crédito adicional, escriba un programa que reconstruya la entrada de la salida.
fuente
Respuestas:
GolfScript,
111108 caracteresEste es un enfoque bastante torpe con GolfScript. La segunda versión funciona mucho mejor que la inicial. Es mucho más largo que el código previsto, pero mi implementación había anidado do-loops y esto causó problemas con el intérprete.
Ejemplos:
fuente
Retraído: el algoritmo no puede manejar todos los casos.
C, 422 (arreglado para eliminar dups en la salida y caracteres descartados)Implementación inicial, comenzará a jugar golf.
Dado que las reglas no requieren que realmente comprima este enfoque ingenuo de fuerza bruta ...
Puede procesar 65535 de longitud en 10 segundos
Ejecución de muestra:
fuente