Можна стиснути деякі види даних, наприклад людський текст або вихідний код, прямолінійними граматиками. Ви в основному створюєте граматику, мова якої має саме одне слово - нестиснені дані. У цьому завданні ви повинні написати програму, яка реалізує цей метод збору даних.
Вхідні дані
Вхід - це рядок довжиною не більше 65535 байт. Гарантується, що вхід відповідає регулярному виразу [!-~]+
(тобто, принаймні, одному друкованому символу ASCII, виключаючи пробіли).
Приклад введення:
abcabcbcbcabcacacabcabab
Вихідні дані
Вихід - це набір правил, що утворюють граматику, яка описує рівно одне слово (введення). Кожен нетермінал позначається десятковим числом, більшим за 9. Символ запуску є символом номер десять. Приклад виводу, що відповідає прикладу введення, наведено нижче; його синтаксис описаний далі:
10=11 11 12 12 11 13 13 11 14 14
11=a 12
12=b c
13=a c
14=a b
Кожне правило має форму <nonterminal>=<symbol> <symbol> ...
з правою стороною, розділеною довільною кількістю пробілів. Кожен висновок, який підкоряється наступним обмеженням і походить саме вхідний рядок, є дійсним.
Обмеження
Щоб люди не могли робити дивні речі, існує ряд обмежень:
Кожен нетермінал повинен з’являтися щонайменше двічі з правого боку правила. Наприклад, наступна граматика для введення
abcabc
є незаконною, оскільки правило 12 з’являється лише один раз:10=12 11=a b c 12=11 11
Жодна послідовність двох суміжних символів не може з’являтися більше ніж один раз у всіх правій частині всіх правил, за винятком випадків, коли вони перетинаються. Наприклад, наступна граматика для введення
abcabcbc
є незаконною, оскільки послідовністьbc
відображається двічі:10=11 11 b c 11=a b c
Дійсною граматикою буде:
10=11 11 12 11=a 12 12=b c
Ваша програма повинна закінчуватися менш ніж за одну хвилину на кожен дійсний вхід, який не перевищує 65535 байт.
Як звичайно, ви не можете використовувати будь-які засоби вашої мови або будь-яку функцію бібліотеки, яка робить рішення тривіальним або реалізує значну частину його.
Зразок введення
Згенеруйте зразок введення за допомогою наступної програми 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;
}
Зразок введення, згенерований програмою вище, зазвичай не призведе до хороших результатів стиснення. Розглянемо використання людського тексту або вихідного коду в якості прикладу введення.
Критерії виграшу
Це код гольфу; виграє програма з найкоротшим вихідним кодом. Для отримання додаткового кредиту напишіть програму, яка реконструює вхідні дані.