Хто хоче стати переможцем складності Колмогорова?


22

Ваша місія сьогодні - створити текстовий компресор.

Завдання

Ви напишете дві функції:

  • Пакера є функцією , яка приймає рядок ASCII символів (U + 0000 до U + 007F) і виводить рядок Unicode (U + 0000 до U + 10FFFF), що містять найменшу кількість символів можливо.

  • Розпакувальник це функція , яка приймає кодовані рядки Unicode і виводить в точності вихідної рядки ASCII.

Вхідні дані

Єдиний дозволений вхід - це рядок ASCII (для пакувальника) та упакована рядок Unicode (для упаковки). Ні вводу користувача, ні підключення до Інтернету, ні використання файлової системи.

Ваші функції можуть мати доступ до цього списку англійських слів . Ви можете використовувати цей список як локальний файл txt або скопіювати його вміст у вихідний код у вигляді рядка або масиву рядків .

Ви не можете жорстко кодувати фрагменти нижче у своїх функціях.

Вихідні дані

Єдиний дозволений вихід для обох функцій - це рядок.

Вихід розпакувальника повинен містити точно такі ж символи, що і вхід пакера.

Ваші входи та виходи можуть використовувати будь-яке кодування символів, що підтримує всі Unicode (UTF-8/16/32, GB18030, ...), оскільки оцінка буде залежати лише від кількості символів Unicode у висновку. Будь ласка, уточніть, яке кодування ви використовуєте.

Щоб підрахувати кількість символів Unicode у вашому виході, ви можете скористатися цим інструментом: http://mothereff.in/byte-counter

Оцінка балів

Ваш запис повинен мати можливість упакувати та розпакувати 10 наступних текстових фрагментів (які я взяв на цьому форумі).

Ваш результат буде сумою розмірів ваших 10 упакованих рядків (символами Unicode) + розміром ваших двох функцій (також у символах Unicode)

Не рахуйте розмір словника, якщо ви його використовуєте.

Будь ласка, включіть у свої записи "бал" кожного фрагмента та їх упаковану версію.

Виграє найнижчий рахунок.

Дані

Ось фрагменти для кодування для обчислення вашої оцінки:

1: Текст Ріка Ролла (1870b): Нам не дивно кодувати гольф, ви знаєте правила, і так я

Нам не чужих любити
Ви знаєте правила, і я
Повна прихильність - це те, про що я думаю
Ви б не отримали цього від жодного іншого хлопця
Я просто хочу сказати тобі, як я себе почуваю
Треба зрозуміти

Ніколи не здадуся тобі
Ніколи тебе не підведу
Ніколи не біжу і покине тебе
Ніколи не змусить тебе плакати
Ніколи не прощаюся
Ніколи не скажу неправду і не зашкодить тобі

Ми так довго знаємось
Ваше серце болить, але
Ти занадто сором’язливий, щоб сказати це
Всередині ми обоє знаємо, що відбувається
Ми знаємо гру і будемо її грати
І якщо ви запитаєте мене, як я себе почуваю
Не кажи мені, що ти занадто сліпий, щоб бачити

Ніколи не здадуся тобі
Ніколи тебе не підведу
Ніколи не біжу і покине тебе
Ніколи не змусить тебе плакати
Ніколи не прощаюся
Ніколи не скажу неправду і не зашкодить тобі

Ніколи не здадуся тобі
Ніколи тебе не підведу
Ніколи не біжу і покине тебе
Ніколи не змусить тебе плакати
Ніколи не прощаюся
Ніколи не скажу неправду і не зашкодить тобі

(Ой, здавайся)
(Ой, здавайся)
(Ой)
Ніколи не дам, ніколи не дам
(Відмовитись)
(Ой)
Ніколи не дам, ніколи не дам
(Відмовитись)

Ми так довго знаємось
Ваше серце болить, але
Ти занадто сором’язливий, щоб сказати це
Всередині ми обоє знаємо, що відбувається
Ми знаємо гру і будемо її грати

Я просто хочу сказати тобі, як я себе почуваю
Треба зрозуміти

Ніколи не здадуся тобі
Ніколи тебе не підведу
Ніколи не біжу і покине тебе
Ніколи не змусить тебе плакати
Ніколи не прощаюся
Ніколи не скажу неправду і не зашкодить тобі

Ніколи не здадуся тобі
Ніколи тебе не підведу
Ніколи не біжу і покине тебе
Ніколи не змусить тебе плакати
Ніколи не прощаюся
Ніколи не скажу неправду і не зашкодить тобі

Ніколи не здадуся тобі
Ніколи тебе не підведу
Ніколи не біжу і покине тебе
Ніколи не змусить тебе плакати
Ніколи не прощаюся
Ніколи не скажу неправду і не зашкодить тобі

2: Гольфіст (412b): Golfing ASCII-art

      '\. . |> 18 >>
        \. '. |
       O >>. 'о |
        \. |
        / \. |
       //. |
 jgs ^^^^^^^ `^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^

3: алмаз числа (233b): Друкуйте цей алмаз

        1
       121
      12321
     1234321
    123454321
   12345654321
  1234567654321
 123456787654321
12345678987654321
 123456787654321
  1234567654321
   12345654321
    123454321
     1234321
      12321
       121
        1

4: алфавіт чотири рази (107b): друк алфавіту чотири рази

а Б В Г Г Д Е Є Ж З И І Ї Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ ью я
qwertyuiopasdfghjklzxcvbnm
pyfgcrlaoeuidhtnsqjkxbmwvz
zyxwvutsrqponmlkjihgfedcba

5: Лірика Старого Макдональдса (203b): функція Old MacDonald

Старий Макдональд мав ферму, EIEIO,
І на цій фермі у нього була корова, EIEIO,
З му-му тут і з му-му,
Тут му, там му, скрізь му,
Старий Макдональд мав ферму, EIEIO!

6: Текст пісні рок цілодобово (144b): Рок навколо годинника

1, 2, 3 години, 4 години рок,
5, 6, 7 годин, 8 годин рок,
9, 10, 11 годин, 12 годин рок,
Ми сьогодні будемо гойдатися цілодобово.

7: Hello World (296b): скажіть "Hello" світові в мистецтві ASCII

 _ _ _ _ _ _ _
| | | | ___ | | | ___ __ _____ _ __ | | __ | | |
| | _ | | / _ \ | | / _ \ \ \ / \ / / _ \ | '__ | | / _` | |
| _ | __ / | | (_) | \ VV / (_) | | | | (_ | | _ |
| _ | | _ | \ ___ | _ | _ | \ ___ () \ _ / \ _ / \ ___ / | _ | | _ | \ __, _ (_)
                    | /

8: Ірландське благословення (210b): Старе ірландське благословення

Нехай дорога підійде вам назустріч
Нехай вітер буде завжди у вас на спині
Нехай сонце зігріває на вашому обличчі
Дощі падають на ваших полях
І поки ми знову не зустрінемося
Нехай Бог тримає тебе в дуплі своєї руки

9: Була лірика старої леді (1208b): Була стара леді

Була стара баба, яка ковтала муху.  
Я не знаю, чому вона проковтнула цю муху,  
Можливо, вона помре.

Була стара пані, ковтала павука,  
Це викручувалось, замикалось і ковтало всередині неї.  
Вона проковтнула павука, щоб зловити муху,  
Я не знаю, чому вона проковтнула цю муху,  
Можливо, вона помре.

Була стара баба, ковтаючи птаха,  
Як безглуздо ковтати пташку.  
Вона проковтнула птаха, щоб зловити павука,  
Вона проковтнула павука, щоб зловити муху,  
Я не знаю, чому вона проковтнула цю муху,  
Можливо, вона помре.

Була стара жінка, яка ковтала кота,  
Уявіть, що ковтати кота.  
Вона ковтала кота, щоб спіймати птаха,  
Вона проковтнула птаха, щоб зловити павука,  
Вона проковтнула павука, щоб зловити муху,  
Я не знаю, чому вона проковтнула цю муху,  
Можливо, вона помре.

Була стара жінка, яка ковтала собаку,  
Що за свиня ковтати собаку.  
Вона ковтала собаку, щоб зловити кота,  
Вона ковтала кота, щоб спіймати птаха,  
Вона проковтнула птаха, щоб зловити павука,  
Вона проковтнула павука, щоб зловити муху,  
Я не знаю, чому вона проковтнула цю муху,  
Можливо, вона помре.

Була стара жінка, яка ковтала коня,  
Вона померла, звичайно.

10: адреса gettysburg (1452b): наскільки випадковою є адреса Геттісбурга

Чотири бали і сім років тому наші батьки народили на цьому континенті нову націю, задуману на волі, і присвятили судження про те, що всі люди створені рівними. Зараз ми ведемо велику громадянську війну, перевіряючи, чи може ця нація, чи будь-яка нація, задумана та настільки віддана, довго витримає. Нас зустрічають на великому полі бою тієї війни. Ми присвятили присвятити частину цього поля як остаточного місця відпочинку тих, хто тут віддав своє життя, щоб жила ця нація. Ми повинні робити це цілком належно і правильно. Але, у більшому сенсі, ми не можемо присвятити, ми не можемо освятити, ми не можемо освятити цю землю. Хоробрі люди, живі та мертві, які боролися тут, освятили його, набагато вище нашої бідної сили, щоб додати чи применшити. Світ мало помітить, ані довго пам’ятатиме, що ми тут говоримо, але ніколи не можна забути, що вони тут зробили. Саме для нас, живих, тут ми будемо присвячені незавершеній роботі, яку вони, хто воював тут, поки що знатно просунулися. Ми швидше тут будемо присвячені великому завданню, що залишилося перед нами - щоб ми з цих шанованих мертвих зробили більшу відданість тій справі, за яку вони дали останню повну міру відданості, - що ми тут вирішуємо, що ці мертві не будуть даремно померли - що цей народ, при Бозі, матиме нове народження свободи, і що державна влада народу, для народу, не загине від землі.

Всього (нестиснене): 6135 символів / байт.

Веселіться!


7
Це не складний спосіб винайти мову, це завдання щось стиснути.
Джастін

2
Я думаю, що не враховуючи розмір компілятора / виконавця (компресор / декомпресор) в рахунок робить це завдання трохи відкритим. У якийсь момент лінія між словником і жорстким кодуванням стане дуже тонкою.
Денніс

2
Дарн, і ось я вже друкував private static final String RICK_ROLL_RETURN = "We're no strangers to love...
Теорія графіків

1
Я не думаю, що ви зверталися до спостереження Денніса.
Пітер Тейлор

1
@xem Я думаю, що публікацію можна покращити, організувавши інформацію в такі розділи, як #Task, #Input, #Output, #Scoring. Я також вважаю, що розмір вихідного коду для компресора та декомпресора повинен бути включений до оцінки. Це нічого не шкодить, але це вирішує проблему, яку вказував Денніс.
Rainbolt

Відповіді:


6

Хаскелл - 5322 бали

Байти коду: 686

Оригінальний розмір: 6147 = 1871+415+234+108+204+145+297+211+1209+1453

Розмір закодованого: 4636 = 1396+233+163+92+153+115+197+164+979+1144

Оцінка: 686+ 4636

Стиснення числа символів: ~25%

Код

Окрім оптимізацій, це зберігає значення між символами Unicode 0та 7fв них як основні фактори.

Це не зменшує кількість байтів кодованого виводу, лише знижує кількість символів Unicode. Наприклад, тест # 4 містить 108символи і кодований вихідний сигнал, 92. Однак їх розміри - це 108і 364байти.

import Data.Bits
import Data.List
import Data.Numbers.Primes
import qualified Data.Text as T
a=nub$concat$map(primeFactors)[0..127]
d(a:r)c=let s=shift c 5in if s<=0x10ffffthen d r(s+a)else c:d r a
d[]c=[c]
f(a:r)=let o=a.&.0x1fin(if o/=a then f((shiftR a 5):r)else f r)++[o]
f[]=[]
g=T.pack.map(toEnum).(\(a:r)->d r a).concatMap j.map(map(\x->head$elemIndices x a)).map(primeFactors.fromEnum).T.unpack
h=T.pack.map(toEnum.product.map((!!)a)).i.f.reverse.map(fromEnum).T.unpack
i(a:r)=let z=a`clearBit`4;x=if a`testBit`4then(take z$repeat$head r,tail r)else splitAt z r in[fst x]++i(snd x)
i[]=[]
j x@(a:_)=let l=length x in if(take l(repeat a))==x then[l`setBit`4,a]else[l]++x
j[]=[0]

Як це працює

  • Кодування

    1. Кожен символ перетворюється в його числовий еквівалент, дозволяє називати це число n.
    2. nпотім перетвориться в список своїх головних чинників, ps.
      • Зручно буває, що числа 0 до 127 мають 32 загальних простих множників, виключаючи 1. Це означає, що вони, чинники, можуть бути збережені як індекси всього на 5 біт.
      • 1 є окремим випадком і представлений порожнім списком.
    3. З psкодування зараз можна починати.
      1. Кожне число psперетворюється в його індекс у списку 32 унікальних факторів (У наведеному вище коді цей список ідентифікований як a).
      2. (Майте на увазі, на даний момент ми маємо справу зі списком списку індексів основних факторів). Щоб перейти до наступного кроку, psйого потрібно вирівняти. Для збереження цілісності даних кожен список перетворюється в інший список з двох частин
        1. Перший елемент зберігає свою довжину, і якщо він складається з того ж фактора.
          • У списку є щонайбільше 6 простих коефіцієнтів, ця інформація зберігається на найменших правіших 3 бітах. П'ятий біт використовується як прапор, щоб вказати, що список складається з одного фактора.
        2. Решта елементів - це самі індекси або один індекс, якщо в списку менше двох різних факторів.
      3. Ці списки потім об'єднуються в один зведений список, fs.
    4. Елементи fsсимволу потім можуть бути упаковані в символи unicode, використовуючи бітове зміщення.
  • Розшифровка

    • Виконайте дії кодування в зворотному порядку.
    • Якщо вам цікаво, як це 1вписується, я хотів би нагадати вам про це product [] == 1.

Тести

Використання цього інтерфейсу для тестування було б болісним, тому я використав цю функцію, щоб надати нижче результати.

edTest f = do
    t <- readFile f
    let txt = T.pack t
        enc = g txt
        dec = h enc
        tst = txt == dec
    putStrLn $ (show $ T.length txt) ++ "," ++ (show $ T.length enc) ++ "," ++ (show $ T.length dec)++","++(show tst)
    putStrLn $ if not tst then T.unpack txt ++ "\n---NEXT---\n" ++ T.unpack dec else ""


λ> edTest "1"
1871,1396,1871,True

λ> edTest "2"
412,233,412,True

λ> edTest "3"
234,163,234,True

λ> edTest "4"
108,92,108,True

λ> edTest "5"
204,153,204,True

λ> edTest "6"
145,115,145,True

λ> edTest "7"
297,197,297,True

λ> edTest "8"
211,164,211,True

λ> edTest "9"
1209,979,1209,True

λ> edTest "10"
1453,1144,1453,True

Зразок

Вихід функції кодування gдля тесту №4 - це це,
"\99429\582753\135266\70785\35953\855074\247652\1082563\68738\49724\164898\68157\99429\67973\1082404\587873\73795\298017\330818\198705\69861\1082435\595009\607426\36414\69873\855074\265249\346275\67779\68738\77985\1082513\821353\132131\101410\247652\1082562\49724\164898\67649\594977\34915\67746\50273\135265\103997\563265\103457\1086021\99399\584802\70753\73889\34882\582722\411459\67779\68740\1084516\1082563\1091681\103491\313282\49724\164897\68705\135741\69858\50241\607426\35905\608421\1082435\69858\50274\71777\43075\298018\280517\1082404\67971\36017\955425\67665\919600\100452\132129\214883\35057\856097\101474\70753\135737"
або якщо ви вмієте гнучко, це
𘑥򎑡𡁢𑒁豱󐰢𼝤􈓃𐲂숼𨐢𐨽𘑥𐦅􈐤򏡡𒁃񈰡񐱂𰠱𑃥􈑃򑑁򔓂踾𑃱󐰢񀰡񔢣𐣃𐲂𓂡􈒑󈡩𠐣𘰢𼝤􈓂숼𨐢𐡁򑐡衣𐢢쑡𡁡𙘽򉡁𙐡􉉅𘑇򎱢𑑡𒂡衂򎑂񤝃𐣃𐲄􈱤􈓃􊡡𙑃񌟂숼𨐡𐱡𡈽𑃢쑁򔓂豁򔢥􈑃𑃢쑢𑡡ꡃ񈰢񄟅􈐤𐦃貱󩐡𐡑󠠰𘡤𠐡𴝣裱󑀡𘱢𑑡𡈹

Додаткові примітки

  • Використання http://mothereff.in/byte-counter , списки каталогів та edTestрозмір тестів відповідають усім, але все ж відрізняються від вказаного розміру у питанні.
  • Тест №10 містить пару EM DASHes ( ), які я замінив- , так як вони знаходяться поза 0- 7fдіапазону.
  • Подальше стиснення може бути досягнуто за допомогою решти четвертого біта при вирівнюванні, наприклад, 00базового корпусу,01 повторення всіх, 10повтору, крім останнього, 11повтору, крім двох останніх.
  • Тестові файли та код доступні тут https://github.com/gxtaillon/codegolf/tree/master/Kolmogorov

Привіт, дякую за цю відповідь! :) Я не розумію , що відбувається в двійковому коді при перетворенні abcdefghijklm...в 𘑥򎑡𡁢𑒁豱󐰢𼝤..., могли б ви пояснити це трохи більше , будь ласка? Крім того, я виправив підрахунок знаків та перетворив ем-тире в №10 у питанні. Хоча мої рахунки все ще відрізняються від ваших. Не знаю чому, я використав інструмент mothereff.in.
xem

@xem Складні деталі розкриті.
gxtaillon

Мій розум (образно кажучи) буквально роздутий думкою про те, що числа 0 і 2-127 можна закодувати на 5 біт. Ви знайшли це самостійно чи це було щось відоме? Питання про бонус: скільки бітів потрібно, щоб зберігати лише друковані символи ascii, тобто 95 різних символів?
xem

@xem Числа не кодуються по 5 біт, кожен з їх факторів є. Я був би дуже радий, якби знайшов спосіб кодування 7 біт лише на 5. Що стосується символів ascii, для цього методу їм все одно знадобиться по 5 біт.
gxtaillon

1
Оскільки у вказаному вами діапазоні є щонайбільше 6 коефіцієнтів на число, у довжині використовується 3 з 5-ти бітових "блоків". Тоді індекси кодуються по 5 біт, так. У цій реалізації використовується один з 2 невикористаних бітів у блоці довжини для отримання додаткового стиснення.
gxtaillon

4

C ++ (C ++ 11), 2741 балів

У цій відповіді використовується UTF-32 як кодування стисненого тексту.

#include <cstdio>
#include <iostream>
#include <locale>
#include <string>
#define L locale
using namespace std;long b,n,i,l;void c(){string d;char x;while((x=cin.get())!=EOF)d+=x;b=(d.size()*7)%20;n=5;wcout.imbue(L());for(char y:d){b=b<<7|y&127;n+=7;if(n>=20)wcout.put(b>>(n-=20)&0xFFFFF);}if(n)wcout.put(b<<20-n&0xFFFFF);}void d(){wstring d;wchar_t w;wcin.imbue(L());while((w=wcin.get())!=EOF)d+=w;l=-1;for(wchar_t y:d){b=b<<20|y;n+=20;if(l<0)l=b>>15&31,n-=5;while(n>=7&(i<d.size()-1|n>20-l))cout.put(b>>(n-=7)&127);++i;}}int main(int t,char**a){L::global(L("en_US.utf8"));**++a<'d'?c():d();}

Підрахунки та забивання балів

Код: 593 символів (задній рядок позбавлений)

Стислі тексти (символи unicode) : 654 + 145 + 82 + 38 + 51 + 104 + 73 + 423 + 506 = 2148 (рахується з wc -mкількістю символів unicode, а не байтами, кількість байтів - як у відповіді @ gxtaillon , що перевищує оригінали, загалом 8413 байт, як підраховано wc -c).

Коефіцієнт стиснення (ASCII до unicode) : 35,01% (використовуючи 6135 байт із запитання (те саме, що wc -c))

Остерігайтеся:

Багато оболонок не можуть обробляти символи Unicode, які виробляє ця програма. Таким чином, декомпресія може призвести до того, що текст десь буде відрізаний, коли оболонка не може обробити символ, оскільки введення здійснюється черезstdin оболонку.

Складання

Він повинен зібрати з clang++і g++ -std=c++11, але він буде показувати деякі попередження про пріоритет операцій, як вираз , як b<<20-n&0xFFFFFне розглядатиметься як ((b << 20) - n) & 0xFFFFF, як можна було б очікувати, а як (b << (20 - n)) & 0xFFFFF.

Використання

  • Складіть програму у виконуваний файл, наприклад ./compress.
  • Запустіть програму ./compress cдля стиснення або ./compress dрозпакування. (Обережно, вимикаючи опцію, дає SEGFAULT (перевірка помилок настільки дорога для символів ...), а інші варіанти (наприклад, використання Dзамість d) можуть дати несподівані результати
  • Вхід зчитується з, stdinа вихід записується вstdout

Як це працює

Безумовно

#include <cstdio>
#include <iostream>
#include <locale>
#include <string>

using namespace std;

long b, n, i, l;

// Compress
void c() {
    string d;
    char x;
    // Read from STDIN until EOF
    while((x = cin.get()) != EOF)
        d += x;
    // Calculate the number of bits used from the last unicode character
    // (maximum 19) and store it into the first 5 bits
    b = (d.size() * 7) % 20;
    n = 5;
    // Set the output locale to allow unicode
    wcout.imbue(locale());
    // For each character in the input...
    for (char y : d) {
        // Add its bit representation (7 bits) to the right of the buffer
        // by shifting the buffer left and ORing with the character code
        b = (b << 7) | (y & 127);
        // Add 7 to the bit counter
        n += 7;
        // If enough data is present (20 bits per output character),
        // calculate the output character by shifting the buffer right,
        // so that the last 20 bits are the left 20 bits of the buffer.
        // Also decrement the bit counter by 20, as 20 bits are removed.
        if (n >= 20)
            wcout.put((b >> (n -= 20)) & 0xFFFFF);
    }
    // If there are still bits in the buffer, write them to the front of
    // another unicode character
    if (n)
        wcout.put((b << (20 - n)) & 0xFFFFF);
}

// Decompress
void d() {
    wstring d;
    wchar_t w;
    // Set STDIN to UNICODE
    wcin.imbue(locale());
    // Read wide characters from STDIN (std::wcin) until EOF
    while ((w = wcin.get()) != EOF)
        d += w;
    // `l' represents the number of bits used in the last unicode character.
    // It will be set later
    l = -1;
    // For each input character...
    for (wchar_t y : d) {
        // Add it to the buffer and add 20 to the bit counter
        b = (b << 20) | y;
        n += 20;
        // If the number of bits in the last unicode character has not been
        // set yet, read the first 5 buffer bits into `l'. This is
        // necessary because the last character may contain more than 7
        // (one entire uncompressed character) unused bits which may
        // otherwise be interpreted as garbage.
        if (l < 0) {
            l = (b >> 15) & 31;
            n -= 5;
        }
        // As long as there is data to turn into output characters
        // (at least 7 bits in the buffer and either not the last
        // unicode character or before the unused bits)
        while (n >= 7 && ((i < d.size() - 1) || (n > (20 - l)))
            cout.put((b >> (n -= 7)) & 127); // Output the left 7 bits in the buffer as an ASCII character
        ++i; // Increment the character index, so that we know when we reach the last input character
    }
}
int main(int t, char**a) {
    // Set the default locale to en_US.utf8 (with unicode)
    locale::global(locale("en_US.utf8"));
    // Decide whether to compress or decompress.
    // This is just fancy pointer stuff for a[1][0] < 'd' ? c() : d()
    (**(++a) < 'd') ? c() : d();
}

Пояснення

Оскільки всі символи Юнікоду з U+0000до U+10FFFFдозволені, ми можемо використовувати 20 біт на юнікод напівкоксу:U+FFFFF використовує 20 біт і по - , як і раніше включений в допустимих межах. Таким чином, ми просто намагаємося затиснути всі окремі біти символів ASCII в символи unicode для зберігання декількох символів ASCII в одному символі unicode. Однак нам також потрібно зберегти кількість бітів, використаних в останньому символі unicode, тому що невикористані бітові сміття в іншому випадку можуть бути інтерпретовані як належно стислі символи ASCII. Оскільки максимальна кількість використаних бітів в останньому символі Unicode дорівнює 20, нам знадобиться 5 біт для цього, які розміщуються на початку стислих даних.

Приклад виведення

Це вихід для прикладу №4 (як задано less):

<U+4E1C5><U+8F265><U+CD9F4><U+69D5A><U+F66DD><U+DBF87><U+1E5CF><U+A75ED>
<U+DFC79><U+F42B8><U+F7CBC><U+BA79E><U+BA77F>쏏𦛏<U+A356B><U+D9EBC><U+63ED8>
<U+B76D1><U+5C3CE><U+6CF8F><U+96CC3><U+BF2F5><U+D3934><U+74DDC><U+F8EAD>
<U+7E316><U+DEFDB><U+D0AF5><U+E7C77><U+EDD7A><U+73E5C><U+786FD><U+DB766>
<U+BD5A7><U+467CD><U+97263><U+C5840>

( 쏏𦛏введіть <U+C3CF><U+266CF>як символьні коди, але я, можливо, помилився)


2

Пітон 3, 289 + 818 = 1107 балів

Тільки злегка гольф.

import zlib as Z
def p(s):
 z=int.from_bytes(Z.compress(s),'big');o=''
 while z:
  z,d=divmod(z,1<<20)
  if d>0xd000:d+=1<<16
  o+=chr(d)
 return o[::-1]
def u(s):
 i=0
 for c in s:
  d=ord(c)
  if d>0xe000:d-=1<<16
  i=(i<<20)+d
 return Z.decompress(i.to_bytes(i.bit_length()//8+1,'big'))

Загальний розмір коду - 289 байт, і кодує задані 6135 байт на 818 символів Unicode - загальна кількість вихідних байтів становить 3201 байт, що значно менше, ніж вихідні входи.

Кодує за допомогою zlib, потім вторинно використовуючи кодування unicode. Деякі додаткові логіки були потрібні, щоб уникнути сурогатів (яких Python насправді ненавидить).

Приклад виведення з №4, як видно з less(37 символів Unicode):

x<U+AC0DC><U+BB701><U+D0200><U+D00B0><U+AD2F4><U+EEFC5>𤆺<U+F4F34>멍<U+3C63A><U+2F62C><U+BA5B6><U+4E70A><U+F7D88><U+FF138><U+40CAE>
<U+CB43E><U+C30F5><U+6FFEF>𥠝<U+698BE><U+9D73A><U+95199><U+BD941><U+10B55E><U+88889><U+75A1F><U+4C4BB><U+5C67A><U+1089A3><U+C75A7>
<U+38AC1><U+4B6BB><U+592F0>ᚋ<U+F2C9B>

Програма драйвера для тестування:

if __name__ == '__main__':
    import os
    total = 0
    for i in range(1,10+1):
        out = p(open('data/%d.txt'%i,'rb').read())
        total += len(out)
        open('out/%d.bin'%i,'w',encoding='utf8').write(out)
    print(total)
    for i in range(1,10+1):
        out = u(open('out/%d.bin'%i,'r',encoding='utf8').read())
        open('data2/%d.txt'%i,'wb').write(out)

Кількість вихідних байтів:

 607 out/1.bin
 128 out/2.bin
 101 out/3.bin
 143 out/4.bin
 177 out/5.bin
 145 out/6.bin
 186 out/7.bin
 222 out/8.bin
 389 out/9.bin
1103 out/10.bin
3201 total

1
Чи не факт, що для цього використовується бібліотека стиснення, яка обманює трохи?
Бета-розпад

@BetaDecay: Це не обмежує це питання, тому я подумав, що це чесна гра.
nneonneo

Також потрібно включити декомпресор.
Бета-розпад

@BetaDecay: pце пакувальник, uрозпаковувач.
nneonneo

1

Пітон 2 - 1141 бали

from zlib import *;v=256
def e(b):
 x=0
 for c in compress(b,9):x=(x*v)+ord(c)
 b=bin(x)[2:]
 return "".join(unichr(int("1"+b[a:a+19],2))for a in range(0,len(b),19))
def d(s):
 y=int("".join(bin(ord(a))[3:]for a in s),2);x=""
 while y:y,d=(y/v,chr(y%v));x=d+x
 return decompress(x)

Розмір коду - 281байти, і він кодує 6135байти860 символи unicode.

Як це працює:

Для кодування:

  1. Стисніть рядок для кодування.
  2. Інтерпретуйте стислий рядок як базове 256 число.
  3. Перетворити число у двійкове.
  4. Розділіть двійкове зображення на групи 19бітів, додайте 1трохи до початку кожного з них, а потім перетворіть у символи Unicode.

Розшифровка - це зворотне.

Зауважте, що деякі версії python можуть обробляти лише символи unicode до 0xFFFF, і таким чином цей код підніме a ValueError.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.