Здравствуйте Необходимо сжимать короткие сообщения (несколько десятков байт). Сообщения это обычный тект, короткие фразы. Посоветуйте оптимальный алгоритм(желательно с исходниками, можно на любом языке). Решил использовать lzw, но пока не уверен
Ну могу предложить один вариант. (Изврат полный) Если передается текст водишь свой словарь из часто используемых слов и нумеруешь их по порядку. А передаешь порядковый номер в словаре. Недостаток: нужно сделать такой словарь и хранить его на источнике и получателе, а если меняется то синхронизировать их. Т.о. в 10 байт можно поместить 10 слов любой длины. Ну это при условии, что словарь не больше 256 слов.
Я,неточно задачу описал. Несколько десятков байт это минимальная длинна сообщения. Максимальная килобайт 70. RLE не думаю что подойдет, сжимается осмысленный текст, повторений мало. Думаю использовать 2 алгоритма. Для более-менее длинных сообщений lzw, а для коротких арифметическое сжатие, оно, кажется в худшем случае не удлинняет сообщение(или есть другие алгоритмы?). С реальзицией арифметического на асм, думаю будут проблемы, я еще учусь, может у кого-нибудь есть исходники?
Sov лучше арифметика не найти, но он черепаха. оптимумом являются координатки - у них и скорость выше, и на малоизбыточных данных при такой длинне строки они даже арифметик обогнать могут, но выигрыш весьма........ весьма мал. я этим делом одно время занимался, могешь вот тут почитать обсуждение на форуме http://wasm.ru/forum/viewtopic.php?id=19505 (там же и урлосы на описания найдёшь). и кстати, вопрос: по твоей задачи есть возможность склейки сообщений??
UbIvItS Хм... Идея интересная,надо думать... В моей задаче склейка сообщений не предусматривается, хотя, используя коорд это легко сделать, никакой перепаковки... Я сжатием 2-й день занимаюсь, крыша едет от обилия алгоритмов) Пожалуй попробую реализовать этот алгоритм, арифметика сложна А скорость меня не очень волнует, сообщения-то коротенькие
Sov алгосов много, а подходов, на коих они базируются, не превышает пальцев руки: словарные, координатные и статистические. а их обилие исходит из того, что много разных видов данных и требуется адаптация.
Sov Самый простой вариант, если сжимается, например английский текст и нет разницы строчные/прописные буквы -- латинский алфавит - 27 символов + точка + пробел + восклицательны/вопросительный знаки + перевод строки = 32 символа или 2^5 т.е. каждый символ требует 5 бит. На ASCII-символы отводится 8 бит. При кодировании отбрасываешь первые 3 бита, при декодировании 3 нулевых бита восстанавливаешь - коэффицент сжатия 8/5=1,6 для короткого сообщения вполне приемлемо...
Код (Text): ; (с) 2006 Алгоритм сжатия Лимпен - Зива LZW_Decompress proc stdcall src:DWORD, dest:DWORD pushad xor ebx,ebx ; ebx=ctrl_count mov esi,src movzx edx,byte ptr [esi] ; edx=ctrl inc esi mov edi,dest NextByte: bt edx,7 jc IsCodeWord movsb jmp Next IsCodeWord: xor eax,eax lodsb shl eax,8 lodsb mov ecx,eax ;eax=codeword shr ecx,4 ;ecx=phrase_index jecxz Finished push esi mov esi,edi sub esi,ecx and eax,0Fh inc eax inc eax mov ecx,eax rep movsb pop esi Next: shl edx,1 inc ebx cmp bl,8 jb NextByte movzx edx,byte ptr [esi] ;edx=ctrl inc esi xor ebx,ebx jmp NextByte Finished: mov eax,edi sub eax,[dest] mov dword ptr [esp+28],eax popad ret LZW_Decompress endp SearchForPhrase proc stdcall string:DWORD, src:DWORD, max_len:DWORD, best_lenptr:DWORD pushad mov esi,[string] mov edi,esi mov bl,byte ptr [esi] xor edx,edx ;edx=best string mov eax,[best_lenptr] mov dword ptr [eax],1 dec esi NextByte: cmp esi,[src] jb Finished cmp byte ptr [esi], bl jnz NotHere push esi push edi inc esi inc edi mov ecx,max_len mov eax,ecx repe cmpsb sub eax,ecx pop edi pop esi mov ecx,[best_lenptr] cmp eax,[ecx] jbe NotHere mov [ecx],eax mov edx,esi NotHere: dec esi jmp NextByte Finished: mov [esp+28],edx popad ret SearchForPhrase endp LZW_Compress proc stdcall src:DWORD, dest:DWORD, len:DWORD local src_end:DWORD local dest_end:DWORD local phrase_ptr:DWORD local lazy_ptr:DWORD local ctrl_ptr:DWORD local phrase_len:DWORD local lazy_len:DWORD local temp:DWORD pushad mov eax,[src] add eax,[len] mov [src_end],eax mov eax,[dest] add eax,[len] sub eax,3 mov [dest_end],eax xor eax,eax mov [phrase_ptr],eax cdq ;edx=ctrl xor ebx,ebx ;ebx=ctrl_count mov esi,[src] mov edi,[dest] mov [ctrl_ptr],edi inc edi NextByte: cmp esi,[src_end] jge Finished cmp edi,[dest_end] jge Finished inc ebx cmp ebx,9 jnz StillBitsInCode mov eax,[ctrl_ptr] mov byte ptr [eax],dl mov [ctrl_ptr],edi inc edi xor edx,edx mov ebx,1 StillBitsInCode: mov ecx,[src_end] sub ecx,esi cmp ecx,15+2 jbe LenGood mov ecx,15+2 ;ecx=max_len LenGood: mov eax,esi sub eax,4095 cmp eax,[src] jae WindowGood mov eax,[src] WindowGood: mov [temp],eax cmp [phrase_ptr],0 jnz TestLazy invoke SearchForPhrase,esi,[temp],ecx,addr phrase_len mov [phrase_ptr],eax TestLazy: cmp ecx,2 jb CantTestLazy inc esi inc [temp] invoke SearchForPhrase,esi,[temp],ecx,addr lazy_len dec ecx mov [lazy_ptr],eax dec esi CantTestLazy: shl edx,1 cmp [phrase_ptr],0 jz code_literal jecxz code_literal cmp [lazy_ptr],0 jz code_word mov eax,[lazy_len] cmp eax,[phrase_len] jbe code_word code_literal: push [lazy_ptr] pop [phrase_ptr] push [lazy_len] pop [phrase_len] movsb jmp NextByte code_word: or edx,1 mov eax,esi sub eax,[phrase_ptr] shl eax,4 mov ecx,[phrase_len] dec ecx dec ecx and ecx,0Fh or eax,ecx push eax shr eax,8 stosb pop eax stosb add esi,[phrase_len] mov [phrase_ptr],0 jmp NextByte Finished: inc ebx shl edx,1 or edx,1 TryNextBits: cmp ebx,8 jae NoMoreBits shl edx,1 inc ebx jmp TryNextBits NoMoreBits: mov eax,[ctrl_ptr] mov byte ptr [eax],dl xor eax,eax stosw sub edi,[dest] mov [esp+28],edi popad ret LZW_Compress endp
не менее извратный вариант, чем вариант S_Alex. Составляется словарь слогов. Для русского языка из 32 букв - 10 гласных, 20 согласных, 2 знака (тверд/мягкий). 20*10=200 символов под слоги типа С-Г + 10 гласных + 20 согласных + знаки пунктуации (запятая, пробел, перевод строки и т.п.) укладываемся в 256 символов. Тексты сжимаются почти в 2 раза
// Copyright (c) 1993 by Chuck Guzis. All rights reserved // Dr. Dobb's Journal. #207 November 1993. pp. 117, 118, 144, 145. Повторюсь, для коротких текстовых сообщений (от десятков до сотен байт) aPLib оптимален, с увеличением размера текстов выгодны арифметика и PPM (если память некритична).
UbIvItS Одно сообщение) Mikl__ От словарей я решил отказаться, переход от расширенной ascii к "мини" очень интересен. Пожалуй самым эффективным решением окажется. Все гениальное просто) asmlamo Спасибо большое, я все сомневолся на си писать или на асме. Сейчас вопрос решен) Всем большое спасибо
gazlan Я и не подозревал, что нарушил чей-то копирайт, вообще-то сам додумался, но на всякий случай выражаю глубокую благодарность Кирилу и Мефодию за предоставленный алфавит, а также Лоренцу, Максвелу, Гальвани, А.С.Попову, чей неоценимый труд увенчался созданием компьютера, на котором я сейчас работаю
Mikl__ угу. вот так живёшь, живёшь, а вдруг раз - и уже ПЛАГИАТОР. жесть P.S. думаю не всех перечислили