谁想成为Kolmogorov复杂性赢家?


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:里克·罗尔(Rick Roll)歌词(1870b): 我们高尔夫球并不陌生,您知道规则,我也是

我们不是爱的陌生人
你知道规则,我也知道
我想的是全面承诺
你不会从任何其他人那里得到这个
我只是想告诉你我的感觉
要让你明白

绝不会放弃你
永远不会让你失望
永远不会跑来跑去和抛弃你
永远不会让你哭泣
永远不会说再见
永远不会撒谎和伤害你

我们认识很久了
你的心一直在痛,
你不好意思说
内部我们都知道发生了什么事
我们知道游戏,我们会玩
如果你问我感觉如何
不要告诉我你太盲目看不见

绝不会放弃你
永远不会让你失望
永远不会跑来跑去和抛弃你
永远不会让你哭泣
永远不会说再见
永远不会撒谎和伤害你

绝不会放弃你
永远不会让你失望
永远不会跑来跑去和抛弃你
永远不会让你哭泣
永远不会说再见
永远不会撒谎和伤害你

(哦,给你)
(哦,给你)
(哦)
永不放弃,永不放弃
(放弃你)
(哦)
永不放弃,永不放弃
(放弃你)

我们认识很久了
你的心一直在痛,
你不好意思说
内部我们都知道发生了什么事
我们知道游戏,我们会玩

我只是想告诉你我的感觉
要让你明白

绝不会放弃你
永远不会让你失望
永远不会跑来跑去和抛弃你
永远不会让你哭泣
永远不会说再见
永远不会撒谎和伤害你

绝不会放弃你
永远不会让你失望
永远不会跑来跑去和抛弃你
永远不会让你哭泣
永远不会说再见
永远不会撒谎和伤害你

绝不会放弃你
永远不会让你失望
永远不会跑来跑去和抛弃你
永远不会让你哭泣
永远不会说再见
永远不会撒谎和伤害你

2:高尔夫球手(412b):高尔夫ASCII艺术

      '\。。|> 18 >>
        \。'。|
       O >>。'o |
        \。|
        / \。|
       //。” |
 jgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^

3:数字菱形(233b):打印此菱形

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

4:四次输入字母(107b):四次打印字母

abcdefghijklmnopqrstuvwxyz
qwertyuiopasdfghjklzxcvbnm
pyfgcrlaoeuidhtnsqjkxbmwvz
zyxwvutsrqponmlkjihgfedcba

5:Old McDonald的歌词(203b):Old MacDonald的功能

老麦克唐纳(Old MacDonald)有一个农场EIEIO,
在那个农场,他有一头母牛,EIEIO,
这里有a,那里有a,
这里a,那里a,到处都是mo,
老麦克唐纳有一个农场,EIEIO!

6:昼夜摇滚(144b):昼夜摇滚

1、2、3点,4点钟
5、6、7点,摇滚8点,
9、10、11点,12点摇滚,
今晚我们将昼夜不停地摇摆。

7:Hello World(296b):向ASCII艺术世界说“ Hello”

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

8:爱尔兰的祝福(210b):古老的爱尔兰祝福

愿这条路升起遇见你
也许风一直在你的身后
愿阳光照在你的脸上
雨水落在你的田野上
直到我们再次见面
愿上帝在你的空洞中抱你

9:有位老太太歌词(1208b):有位老太太

有一个老妇吞下苍蝇。  
我不知道她为什么吞下那只苍蝇,  
也许她会死。

有一个老妇吞下一只蜘蛛,  
那在她体内蠕动,摇摆和摇摆。  
她吞下蜘蛛捉苍蝇,  
我不知道她为什么吞下那只苍蝇,  
也许她会死。

有一个老妇吞下一只鸟,  
吞下鸟真荒谬。  
她吞下那只鸟去捉蜘蛛,  
她吞下蜘蛛捉苍蝇,  
我不知道她为什么吞下那只苍蝇,  
也许她会死。

有一个老妇吞下一只猫,  
想象一下吞下一只猫。  
她吞下猫抓鸟,  
她吞下那只鸟去捉蜘蛛,  
她吞下蜘蛛捉苍蝇,  
我不知道她为什么吞下那只苍蝇,  
也许她会死。

有一个老妇吞下一条狗,  
吞下一只狗真是猪。  
她吞了那只狗来捉住那只猫,  
她吞下猫抓鸟,  
她吞下那只鸟去捉蜘蛛,  
她吞下蜘蛛捉苍蝇,  
我不知道她为什么吞下那只苍蝇,  
也许她会死。

有一位老妇吞下一匹马,  
她当然死了。

10:葛底斯堡(1452b):葛底斯堡地址的随机性

四分制和七年前,我们的祖先在这个大陆上建立了一个新的国家,这个国家是自由构想的,致力于实现人人平等的主张。现在,我们正在进行一场伟大的内战,考验该国家或任何一个如此怀有设想和奉献精神的国家是否可以长期忍受。我们在那场战争的伟大战场上相遇。我们已经将这一领域的一部分奉献给那些在这里献出生命以使该民族得以生存的人们最后的安息之地。我们应该这样做完全合适和适当。但是,从更大的意义上讲,我们不能奉献,我们不能奉献,我们不能圣地。在这里苦苦挣扎的英勇活着的人已经奉献了圣物,远远超出了我们增加或贬损的能力。世界不会注意到,也不会记住我们在这里所说的话,但它永远不会忘记他们在这里做了什么。对我们来说,这是一种生活,而不是专心于未完成的工作,迄今为止,他们在这里奋战的工作迄今还算是很高尚。宁愿我们在这里专注于摆在我们面前的艰巨任务-从这些光荣的死者中,我们更加奉献于他们最后献出充分献身精神的事业-我们在这里坚决解决这些死者不应徒劳地死了-这个国家在上帝的统治下将重生自由-人民的统治,由人民为人民,不会从地上灭亡。

总计(未压缩):6135个字符/字节。

玩得开心!


7
这不是发明一种语言的挑战,这是压缩某些东西的挑战。
贾斯汀

2
我认为,在分数中不包括编译器/执行器(压缩器/解压缩器)的大小会使此挑战有些开放性。在某些时候,字典硬编码之间的界限将变得非常狭窄。
丹尼斯

2
达恩(Darn),在这里我已经在输入文字 private static final String RICK_ROLL_RETURN = "We're no strangers to love...
图论

1
我认为您没有解决丹尼斯的观察。
彼得·泰勒

1
@xem我认为可以通过将信息组织成#Task,#Input,#Output,#Scoring等部分来改进此帖子。我也认为压缩器和解压缩器的源代码大小应包含在分数中。这没有任何伤害,但是可以解决Dennis指出的问题。
Rainbolt 2014年

Answers:


6

Haskell-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%

除了优化之外,这还存储了 0,并7f以Unicode字符作为他们的主要因素。

它不会降低编码输出的字节数,而只会降低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 的编码函数的输出为this,
"\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"
或者,如果您精通乱码,则为this
𘑥򎑡𡁢𑒁豱󐰢𼝤􈓃𐲂숼𨐢𐨽𘑥𐦅􈐤򏡡𒁃񈰡񐱂𰠱𑃥􈑃򑑁򔓂踾𑃱󐰢񀰡񔢣𐣃𐲂𓂡􈒑󈡩𠐣𘰢𼝤􈓂숼𨐢𐡁򑐡衣𐢢쑡𡁡𙘽򉡁𙐡􉉅𘑇򎱢𑑡𒂡衂򎑂񤝃𐣃𐲄􈱤􈓃􊡡𙑃񌟂숼𨐡𐱡𡈽𑃢쑁򔓂豁򔢥􈑃𑃢쑢𑡡ꡃ񈰢񄟅􈐤𐦃貱󩐡𐡑󠠰𘡤𠐡𴝣裱󑀡𘱢𑑡𡈹

附加说明

  • 使用http://mothereff.in/byte-counter,目录列表和edTest测试的大小都是一致的,但仍与问题中指示的大小不同。
  • 测试#10包含几个EM破折号(),-因为它们不在0-中,所以我将其替换为-7f范围内。
  • 在展平时,可以使用剩余的第四位进一步压缩,例如,00基本情况,01全部10重复,除最后一个重复,11重复,除最后两个重复。
  • 测试文件和代码都可以在这里https://github.com/gxtaillon/codegolf/tree/master/Kolmogorov

您好,谢谢您的回答!:)我不明白转换abcdefghijklm...为二进制文件时会发生什么𘑥򎑡𡁢𑒁豱󐰢𼝤...,请您再解释一下吗?另外,在问题中,我固定了字符数并转换了#10中的破折号。不过,我的字符数仍然与您不同。Dunno为什么,我使用了mothereff.in工具。
xem

@xem 复杂的细节已被揭示。
gxtaillon

我的想法(象征性地)被数字0和2-127可以在5位上编码的想法所震惊。您是自己发现的还是已知的?额外的问题:您只需要存储可打印的ascii字符,即95个不同的字符,需要多少位?
xem

@xem数字不是在5位上编码的,它们的每个因子都是。如果能找到一种仅在5个位置上编码7位的方法,我将非常高兴。至于ascii字符,使用这种方法,它们每个仍需要5位。
gxtaillon

1
由于在您指定的范围内,每个数字最多包含6个因数,因此长度使用5位“块”中的3个。然后将索引编码为5位,是的。在此实现中,长度块中2个未使用的比特之一用于获得额外的压缩。
gxtaillon 2014年

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 -mUnicode字符数而不是字节数来计算,字节数与@gxtaillon的答案相同,比原始文件高8413个字节(以计wc -c)。

压缩率(ASCII到Unicode):35.01%(使用问题中的6135字节(与相同wc -c))

谨防:

许多shell无法处理此程序产生的unicode字符。因此,当外壳无法处理字符时,解压缩可能会导致文本被截断,因为输入是stdin从外壳获取的。

编译中

它应使用clang++and进行编译g++ -std=c++11,但会显示有关运算符优先级的警告,因为像这样的表达式b<<20-n&0xFFFFF不会((b << 20) - n) & 0xFFFFF像人们期望的那样被视为,而是(b << (20 - n)) & 0xFFFFF

用法

  • 将程序编译为可执行文件,例如./compress
  • 运行程序以./compress c进行压缩或./compress d解压缩。(小心,省略该选项会产生SEGFAULT(错误检查非常耗费字符...),而其他选项(例如,使用using 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到的Unicode字符,因此每个Unicode字符U+10FFFF可以使用20位:U+FFFFF使用20位,并且仍包含在允许的范围内。因此,我们只是尝试将所有单个ASCII字符填充到Unicode字符中,以在一个Unicode字符中存储多个ASCII字符。但是,我们还需要存储最后一个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

Python 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
这不是使用压缩库作弊的事实吗?
Beta Decay

@BetaDecay:它并没有限制问题,所以我认为这是公平的游戏。
nneonneo

另外,您需要包括一个解压缩器。
Beta Decay

@BetaDecay:p是打包程序,u是解包程序。
nneonneo 2014年

1

Python 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,因此此代码将引发ValueError

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.