趣题:连接多个数字串时怎样避免歧义?

    今天碰上一个非常有意思的问题。有一条通信线路,每次可以发送一个由数字 0 到 9 组成的任意长的数字串。怎样巧妙地利用这条通信线路,构造一种一次能够发送两个数字串的协议?注意到,直接将两个数字串相连是不行的,因为这将会产生歧义。如果对方收到的数字串是 1234 ,他没法知道你发送的是数字串 12 和 34 ,还是数字串 123 和 4 ,抑或是 1 和 234。

    能否把第一个串的位数编码进去,比如把 12 和 34 编码成 21234 ,这样不就知道第一个数字串到哪儿截止了吗?不行,因为你不知道这个位数信息本身到哪儿截止,假如编码结果是 123456789012345 ,你就不知道第一个数字串是 1 位还是 12 位了。换一个思路,能否用几个非常特殊的数字当作分隔符呢?也不行,因为你要发送的数字串里有可能偏偏也包含了这几位数。怎么办呢?


    一种非常容易想到的方法是,把两个数字串都转换为九进制,这样便把数字 9 腾了出来,它就能用作分隔符了。例如,要想发送数字串 12 和 34,只需要把 12 和 34 分别转成九进制,再在他们之间添加一个数字 9,得到数字串 13937,然后发送出去就可以了。即使要发送的数字串中有前导 0 ,问题也不大,我们可以在九进制数前面也加上相同数量的前导 0 。例如,把 012 和 0034 连在一起,也就成了 01390037 ,原始信息中的前导 0 也就很容易识别出来了。

    注意到,把一个十进制数转化成九进制数,数字位数是要增加的。一个值得考虑的问题是,为了实现数字串的连接,采用上述方法需要多花费多少位数字?一个 n 位数的九进制表达,其位数大致可以记作 log(9, 10n) ,也就是 log(9, 10) · n ,大约等于 1.048 n 。因此,把一个 n 位数变成九进制,将会增加 0.048n 位数,似乎是相当节省了。不过,从计算机算法的角度来看,系数再小,它也是 O(n) 的;当数据规模非常大的时候,这个算法的效率并不让人满意。上述算法还有优化的余地吗?

    一个优化方案是,既然首次出现的 9 一定是分隔符,后一个数字串就不必转成九进制了, 12 和 34 只需要编码成 13934 就行了。但是,渐近意义上看,所得数字串的附加长度仍然是 O(n) 。不过,如果和之前“写明第一个串的位数”的思路结合一下,我们就有了一个渐近意义上更优的方案:把第一个串的位数转化为九进制,再添加数字 9 标识出它的右边界即可。如果想要发送数字串 123456789012345 和 12345 ,就可以先数出前一个数有 15 位,再把位数本身转换成九进制 16 ,原始信息便可编码为 16912345678901234512345 。这样一来,附加长度就比原来小得多了,它只有第一个数的位数的 0.048 倍,也就是 0.048 log(n) 了。

    同样是 log(n) 级别的附加长度,我们还有一种更加简单巧妙的方案。将第一个串的位数用“口吃”的方式表达出来,每个数字都重复说一遍,然后加上一对不相同的数字(比如“01”)作为结束标记。例如, 123456789012345 和 12345 就将被编码为 11550112345678901234512345 ,表示第一个数字有 15 位。这样一来,附加的长度就是 2 log(n) + 2 ,同样也是 log(n) 的级别,不过方法简便多了。而且更棒的是,这种方法能够直接扩展到一个更加一般更加困难——两个 01 串的连接!

    大家还能想到什么其他有趣的方案?

 
    Update: 在写上面的文字时,我显然还想得不够多,现在看来让人很不满意。看了大家的回复,我深受启发,决定继续往下说一说。上述方法说穿了就是,用 11 来表示 1 ,用 22 来表示 2 ,一直到用 99 来表示 9 ,然后用 01 来表示分隔。这背后的核心思想其实就是:用两位数字来表示一位数字,从而扩展字符集。因此,我们还可以构造出很多类似的方案来。比方说,用 01 表示 1 ,用 02 表示 2,等等,一直到用 09 表示 9 ,最后用 10 表示分隔符。因此, 123456789012345 和 12345 就可以编码为 01051012345678901234512345 。读取编码后的数字串时,如果读到的是 0?0?0?… 的模式,那么我们都是在读取第一个数字串的位数;什么时候模式被打破了,出现了一个 10 ,第一个数字串的位数也就读完了。

    注意到,扩展字符集的根本动机,就是我们希望能够在字符集中新增加一个分隔符。不过,上面的方案把字符集扩展得太大了,绝大多数新字符其实都没用,实在有些浪费。有办法能够对 {0, 1, 2, …, 9, 分隔符} 这 11 个字符重新编码,使得编码效率又高,连接起来又不会产生歧义吗?不少网友提到了 Huffman 编码,就是专门解决这个问题的。网友 hhb 提到,扩展字符集还有一个更简单的方法:直接把分隔符用 A 来表示,然后把带有分隔符的数字串看作 11 进制数,再转成 10 进制数即可(有前导 0 的话要做保留)。

    转义符的功能不也是这样吗?由于字符串无法表示出换行的概念,于是用 n 表示换行;为了不造成歧义,又规定 \ 表示真正的 。受转义符的启发,我们就有了更好的方案,比方说用 01 表示分隔符,用 00 表示真正的 0 。解码时,每读到一个 0 ,都看看它后面跟的是什么,如果还是一个 0,表明这是一个真正的 0 ;如果是 1 ,则表示分隔符。

    如果看到了新的想法,我再接着补充。

80 条评论

  • xxwzy

    时差党表示抢一个沙发不容易啊

  • xxwzy

    表明位数的时候总觉得还能再省,老是想不出来

  • aihorn_mac

    都好早!算法什么的很喜欢!能推荐一点书目吗?

  • nothing

    其实不用进制转换,用escape的思想就可以了。

    比如发送
    1234 56789
    =》
    123456789

    要发送“”可以用“\”表示

  • 风哥哥8910

    起这么早都抢不到沙发。。。近距离接触一下好啦~

  • Cyker Way

    最后那种方法可以多次重复,复杂度虽然还是lg n,但是是lg n + lg lg n + …,比2 lg n好。再加一点优化是对两个中小的那个重复。难的是证一个下界出来。

  • Qi

    把第一个数的位数放在最后,再用0分开即可。
    123, 45 -> 1234503
    方法简单
    解的时候最后一个0后面的数表示的数A的长度,然后就方便了。

  • Qi

    扩展一下,可以对任意多数字连接。因为表示位数的数字不会包含0

  • Qi

    我是说不会包含前导的0。抱歉,一下子留了三个言。喜欢你的blog

  • 欧龙崎

    很好很强大。

  • Jian

    其实用分隔符的一个思路就是分隔符在正常串中不出现。一个方法就是把所以正常串中的00改写成012,而01改写成011。然后把00作为分隔就可以了。
    另外一个思路就是把第一个串的长度转成9进制使用9作为分隔符号。

  • wzjiang

    最后的方法比较简便,不过简单重复的编码效率有点低,可以让第三位是前两位的和(模十),以不满足这个特征的三位数结尾(如010),位数不是偶数时前面补一个零,这样增加的位数大约是:3/2*lon(n)+3,在位数多时效率高点。

  • zino

    感觉转义比较靠谱点
    01234+567890=0012340567890

  • error 404

    xx9—–yy9———pp9— …… –tt9——-(-)———

    字母为9进制,
    xx表示yy的相对位置,yy表示pp的相对位置……tt表示最后一个串的起始位置。

    这样就能一次发送任意个串了。如果可以的话把最长的串放最后还能节省一点开销……

  • exp618

    在开头像这样写上长度:”001200″表示12位然后连起来就行了
    增加长度log(n)+4

  • zagfai

    @exp618 如果長度1200位呢?… 呵呵

  • zalazan

    ‘9’定义为分隔符,数字9用’99’代替,

  • hhb

    其实从编码角度来考虑,直接添加一个额外的符号作为分隔符,产生一个可能很长的11进制串,然后用算术编码编码一下就行了。熵意义上最优。

  • shadowwalker

    膜拜一下复杂度!我还太嫩,要多指教了

  • 4king

    用转义或者\什么的都不行,人家都说了只能发送0-9这几个数字,要是能发符号什么的还问个P

    楼层: 12a楼 | 2011-06-27 10:38 | zino 说:
    感觉转义比较靠谱点
    01234+567890=0012340567890

    900900+100200你怎么换法?

    = 09009000100200?
    按0来分,究竟是900900还是900900010?

  • Justice

    @20楼:
    人家说的是转义的思想。在计算机程序里一般”都是特殊符号,要真正传递这个字符就用’\’表示。他想说的是如果拿’0’做分隔符,在真正需要传递0的时候就写成’00’。这样,最终传递的过程中,只有单个的’0’才是真正的分隔符。但这会遇到一个问题:如果遇到一串”10001″,会不知道是”10,1″还是”1,01″。按计算机语言处理字符串的转义规则的话不是这样的,我们做下类比可以是:”做转义字符,’n’表示换行;我们这里用’0’做转义字符,’01’表示分隔符。这样,’00’表示0,’01’表示分隔符,单独的’0’不可能出现,就没有二义性了。

  • 依云

    @20L 用 9 作为转义符。用 90 作为分隔符,用 99 来表示数据中本身存在的 9。BTW:如果转义不可行的话,你根本看不到这篇文章,因为网线只能传输 0 和 1 两个数字!

  • morrowind

    隐含的额外信息量应该是log(n)+log(log(n))+…
    小于这个数的方案都是有问题的

  • willzhang

    用转义还不如直接用9进制呢,转义期望下要将0.1n个0变成00,

  • willzhang

    按照原题的思路,可以传3个数,第一个数表示原第一个数是几位数,用9进制数表示。后面加个9。后面2个就是原数。这样的话,最多需要增加 【log【log(n)/log(10) + 1】/log(9) + 1】+1
    【】为取整。
    如果2个数的位数相差很大的话(位数相差100倍以上),可以在第1位再增加个9,来表示给的是第1个数的位数还是第2个数的位数。

  • willzhang

    我好像多打了个Log,其实只有log(n)/log(9) + 2

  • 依云

    @24L 9进制的转换需要消耗不少CPU,而转义使用硬件即可很好地完成。

  • pl

    可以考虑一些无损压缩算法 看起来结果比较乐观

  • pl

    换个角度想
    找一个特殊串作为分隔符 不包含0(比如9999)
    要求第一个数里不包含这个数串
    这个数的最小长度不太会算 1/n! 貌似? 反正应该比log(n)小一点
    [分隔符]0[第一个数][分隔符][第二个数]
    这样排列 是不是更小一点?

  • TooCold

    比口吃表示法改进些的算法:
    用十进制表示第一个数字的位数。但是把所有的0写成00。记这个字符串为xx
    那么总的表示为:
    xx-0-第一个数字-第二个数字
    第一个数量为奇数的连续的0的字符串必然是xx和第一个数字的分界线。
    例如
    1234,5678->4012345678
    1234567890,1234->100012345678901234

    这个方法就是只对0口吃,不对其他数字口吃,复杂度1.1log(n)+1,但是不需要转换进制。

  • TooCold

    另一个更优的解:
    设第一个数字的个位为n。n在第一个数字中共出现了m次。
    我们用只对0口吃的方法表示m,记该字符串为xx。
    总的表示为:
    n-xx-0-第一个数字-第二个数字
    找到第一个数字和xx的分界点的方法和上面类似,只不过是从第二个字符开始找。
    考虑到一个k位的数字,其中一个特定数字出现的期望是k/10

    这个方法的复杂度:1.1log(log(n)/10)+2
    在复杂度上更优,且不需要进制转换。

    例如:

    1234,5678->41012345678
    1234567890,1234->01012345678901234 (这个例子就是比上面少用了一个字符)
    11111111111111111333333355555555888880000000000,1234->01000111111111111111113333333555555558888800000000001234

    数字越大,优势越明显。

  • icanc

    如果数字串长度有限,可以在数字串前设定一个位数足够的数(例如前5位数)来说明数字串要在哪里分开。

  • yh

    这是我鄙视一个叫“算法信息论”的shax东西的理由来着。。。

  • yh

    呃,我被审核了?

  • jim

    我给一个方法,只需要多 log(n)+1的整数部分,而且简单容易
    如这个串 需要传两个数分别是
    第一个 1998位 第二个 7999位 总长9997,如这样
    987487123478…123
    那么在字串最前面添加 (取整)log(9997)+1=4个数 1998(如果位数不足前面补零),
    这个样子: 1998987487123478…123 最后字串长 10001,
    解码时,先对字串长度求一次 k=(取整)log(lenth-log(length))+1 取 前k个数即是第一个数与第二个数的分割点,从剩余的字串中分割获得两个数。

  • plainroc

    另一个方案:
    俩设两个数字串是A和B,那么按照以下步骤来编码:
    1.把A和B直接串起来得到C(如果A和B的顺序无所谓的话可以把短的放在前面以节省总长度,下面总是假设第一个串被称为A)
    2.把A的长度len(A)表示成十进制数,把这个数当作一个数字串,此时个位在右。反转这个串,使得个位在最左边,在这个串的最右边添加无数个0,称此时得到的串为S。
    3.把S中的数字依次插入C中:在S中第k(从0开始计数)个数字插入到C的 (10^k) – 1 位置。注意,插入位置并不把之前插入的S中数字计算在内。如果插入位置已经超过了C的总长度,则停止插入。
    此时得到的C串就可以直接发送出去,解码很简单:在(10^k)-1位置取数字,此时要注意去掉已经取出的数字。把得到的数字反转去掉高位0就得到第一个串的长度。

    举个例子吧:串 0123456789 (长度为10) 和 串 555…555 (1000个5) 的结果是(其中*,!,#是标记):
    *0 012345678 #1 9 555…555(89个5) %0 555…555(910个5) &0 5
    其中*0是个位,在位置0,#1是十位,在位置9,%0是补充的百位,在位置99,&0是补充的千位,在位置999

  • plainroc

    前面写错了,写完了发现其实调换A和B的顺序不能节约总长度,因为要填0

  • karsa

    以0做转义字符,若数字串中本身包含0,则记作00,解码时单个的0是分隔符,连续出现的两个0标示数字串中有一个0.如123+102表示为12301002,解码时读到1230知道第一个数字串是123,读到1后面的两个0,知道原数字串中有一个0.

  • eggcar

    实际中的话是要对每个发送字符做编码的,最基本的是哈弗曼码,可以保证发送码组是即时可译的

  • yoc

    欢迎旁听智能系王老师的信息论:)

  • xz

    Prefix code (Huffman coding) 或者 Escape

  • veloa

    第一个想到的就是huffman code :)

  • Baisk

    呵呵 我再想能不能在9进制的基础上扩展一下,干脆用99进制,用00-98表示这99个数,两位表示一个99进制数,最后用99作为标记第一个字符串长度和第一个字符串的界限。

  • MatCxf

    用LZW编码。现在的压缩软件就是用的这个算法

  • hhb

    假设两个数字总长度L,第一个数字长L1,第二个数字长L2。编码长度N。
    从原文来看接收方是可以隐含知道N的。

    如果L确定时要求N固定。
    显然N>=ceil(log((L-1)*BASE^L))。
    换句话说N和L存在一一对应关系。于是得到总码长就可以知道ceil(log(L-1))。只需要在前面分配固定的位数用于存储L1的长度即可。

    更普遍的情况,假设要发送的两个数字连起来构成的数是M。分隔位置是L1。从原文来看希望给更小的M更短的编码。于是对所有(无穷个)二元组(M,L1)排序。编码即为二元组在排序后数组中的位置。这个不考虑编码效率的话应该是最优编码。

  • biohu

    以前也想过类似的问题。。。

  • Kabie

    还是分组更适合流编码,
    比如7位一组的话,将123456789012345和12345编码为2878342898658674597945,只多占用了2位,
    解码:
    2878342898658674597945转为2进制,8位1组:
    10011100
    00001001
    00001000
    00110000
    00110111
    00111110
    01111001

    11100000
    00111001
    头为1表示一个新的数字,0表示接上一个数字……然后把末7位连起来转回10进制就得到原来的数字了,当然前导0还得另寻办法,好处是允许一次传输任意多个数字

  • justever

    用10做分隔符,当原串中出现10的时候,用101110表示,当遇到一个串为11时,和前后的两个分隔符组成的串101110替换为101010

  • farseerfc

    用最简单的编码第一个数字的长度的方法。
    当第一个数字的长度只有一位时,直接加在最前面。比如:
    encode(“123″,”456”) ===> ‘3123456’
    当第一个数字的长度超过一位时,记录第一个数字的长度的长度,然后是第一个数字的长度,然后是第一个数字,然后是第二个数字。长度的长度也不是一位的时候,以此类推。问题是不知道有多少个长度的长度的长度……的长度,解决方案是在前面加上长度的个数个前导0。比如:
    encode(“1234567890123″,”456”) ===> ‘02131234567890123456’
    encode(“1″*int(1e10) /*1e10个1*/ ,”456”) ===> ‘0021110000000000’+”1″*int(1e10)+’456′
    (上面用的是python语法表示比较大的字符串。)
    用额外的1位表示1e9以内的第一个数。
    额外的4~11位表示10^(1e9)以内的第一个数。
    数的表示范围是指数增长的。
    或者,用递归的方式看
    encode(a,b) ===>
    if len(str(len(a))) <= 1:
    str(len(a))+a+b
    else:
    ‘0’+encode(str(len(a)),a+b)
    就是说,如果第一个数的长度为1,那么编码结果就是长度+第一个数+第二个数。
    否则,结果是以(第一个数的长度)和(第一个数+第二个数)为参数的递归调用的结果,加前导0。

    译码就是先数前导0的个数,然后重复多次的取位数,分割。
    python的实现代码:

    import re
    def encode(a,b):
    l=len(a)
    sl=str(l)
    if len(sl)<2:
    return sl+a+b
    else:
    return “0”+encode(sl,a+b)

    def decode(s):
    nr=len(re.findall(‘^0*’,s)[0])
    rest=s[nr:]
    sl=1; a=””; b=””
    for i in range(0,nr+2):
    a,b=rest[0:sl],rest[sl:]
    sl=int(a);rest=b
    return (a,b)

  • 甘蔗

    同意35楼的方法,简单易行。
    length_of_first_string + first_string + second_string
    具体例子
    strlen(first_string + second_string) < 10, 用1位表示length_of_first_string
    strlen(first_string + second_string) < 100, 用2位表示length_of_first_string

  • shi

    貌似在大牛得博客上看到过另外一个类似得题目,好像是:求一个多项式,但只知道系数是正整数,并且可以输入两个自变量,并得到其结果。

    都是进制得好题目啊

  • Zealot

    题目没有给出两个数的分布情况, 就假设两个数都是在非负整数上平均分布, 那么所有一一映射的解都是最优解.

    f为编码函数, F为解码函数

    f(x, y) = (x+y)(x+y+1)/2 + x
    F(z) = {
    a = ceiling((1/2)*(sqrt(8*z+9)-3))
    y = a(a+3)/2 – z
    x = a – y
    return (x,y)
    }

    ceiling是向上取整函数

    很简单的方法, 用整数铺满二维坐标系的第一象限
    x—>
    y 0 2 5 9 14
    | 1 4 8 13
    | 3 7 12
    | 6 11
    v 10

    纠结于10进制范围内的分隔, 字符串长度, 是基本没可能得到最优解的

  • nextweek

    52楼的方法很非常好,不过如果有前导0的话不知怎么解决。
    35楼的也很不错,不过如果第二个数特别特别大的话,就撑大了总长度

  • 泊桥

    我好想知道博主是数学博士吗?

  • jjx01

    既然每次都发送2组数据,不讲效率的话强制两组数字位数相同,不足的位数前面补0就可以了,比如1和234,就发001234,12和34,就发1234,123和4,就发123004

  • jjx01

    每次必定发送两个字符串的话,强制两个字符串长度一样,短的字符串前加0补全就行了,很容易,不过效率很低,比如1和234,就发001234,12和34,就发1234,123和4,就发123004

  • elf

    12 34 21234
    0 23456123 01023456123
    解码规则,总长度N位 N是M位数
    前M为分割点位置,不足补零

  • Jibber.超

    直接将所需要的程序用2进制表达,再转换成十进制数码,传输后换回2进制,传到电脑后面加上个.exe就完成了。

  • 正和

    49楼的方法和我想的一样,更简单的表述如下:
    设第一个数字有n位,将n写在最前面;
    如果n的位数m<10,编码完成;否则再将0m写在最前面;
    如果m的位数k<10,编码完成;否则再将0k写在最前面;
    重复类推。
    显然,第一个串长度大于0会使编码后的串不可能以01开头,于是还可以用01表示空串。
    举例:
    (1)第一个数有8位,则编码为8x…xy…y
    (2)第一个数有123位,则编码为03123x…xy…y
    (3)第一个数有10亿位,则编码为020101000000000x…xy…y

  • 正和

    出了点差错。更正如下:
    49楼的方法和我想的一样,更简单的表述如下:
    设第一个数字有n位,将n写在最前面;
    如果n的位数m=1,编码完成;否则再将0m写在最前面;
    如果m的位数k=1,编码完成;否则再将0k写在最前面;
    重复类推。
    显然,第一个串长度大于0会使编码后的串不可能以01开头,于是还可以用01表示空串。
    举例:
    (1)第一个数有8位,则编码为8x…xy…y
    (2)第一个数有123位,则编码为03123x…xy…y
    (3)第一个数有10亿位,则编码为020101000000000x…xy…y

  • 帮Jedi武士拿剑的

    给一个 log(n)+1 的解法吧

    其实思路很简单,最后编码分三部分:

    1) 第一个数字为0或1,如果第一个数字较长则为0,反之为1
    2) 较长数字的位数的十进制
    3) 两个数字连在一起
    注意,没有任何分隔符

    容易证明,当两个数字总长度n不是太小的时候,较大数字的长度在n/2到n-1之间。从编码的第二位开始,必然能读取到唯一的“较大数字长度”

    举个例子吧:

    两个数字分别为: 100个1 和 200个2
    则编码为:
    1 200 111…1 222…2

    编码总长度为 304,很容易确定 200 为较长数字长度。如果 取20或者2000作为较长数字长度,都很容易导出矛盾

  • 帮Jedi武士拿剑的

    楼上最后一行有个笔误,2000改为2001 :)

    另外,从信息论不难证明,编码的超出部分不会小于 log(n-1)。所以上面的构造应该比较接近最优了吧

  • 正和

    这个最优标准难以确定,一种是基于两个数字串总长度的最优,另一种是基于第一个数字串长度的最优。“从信息论不难证明编码的超出部分不会小于 log(n-1)”,这隐含了前提:将总长度分成两个串的分割位置是均匀分布的。这个假设其实很任意。比如,还可任意假设数字串取自一个泊松分布或幂分布,这时的最优都不一样。

  • 正和

    如果以两个数字串的总长度n为参照,则以下编码方式最接近log(n-1):
    令k=ceiling(log(n-1+ε)),其中ε为一个任意小的正数。则用k位来表达第一个数字串的长度(不足k位前面加0补足),将这个k位的长度字串作为前缀即可。例如:
    (1)5|6,n=2,k=1,编码为:156
    (2)123456789|0,n=10,k=1,编码为91234567890
    (3)123456789|12,n=11,k=2,编码为0912345678912
    解码的时候不可能出现歧义,证略。

  • 炎羽

    老大…
    这个是通信设计的基础,一点也不有趣,而且很难啊

  • 游客

    不知道上面有没有提到这种:
    发送两个协议头:H1H2
    H2是串1(N1)的位数,H1是H2的位数,
    其中H1规定位数(比如1位,即1-9,则H2为1-9位数)
    增加存储为:lg(N1) + lg(lg(N1))
    可根据N1量级扩展

  • wzjiang

    大家讨论得很有意思,小结一下。35楼、36楼、61楼、64楼都是log(n)的方案,n为总长度,应该接近最优,但都没法提前解出第一个串。30楼、31楼、49楼、60楼等几种方案也很好,比log(n1)稍多一点,n1是第一个串的长度,而且第一个串可以提前解出来。

  • Fourj

    很有趣的问题和答案!
    想到一个解法:压缩重复数字用"口吃"标记重复个数,然后用00表示分隔
    举例:
    12345678+23456 => 123456780023456
    12223456+4566789999 =>13323456004522678449
    最坏的情况为1.5n

  • whknnn

    如果两个字符串长度都不是0可以这样 在每串字符前分别加上三个信息 两个字符串长度和 第一个长度 第二个长度 并且都用0分隔

    比如1000900100 就表示长度和是100 第一个长90 第二个长10

    判断方法是从第一个非0的数开始是第一个数 第二个非0的数开始是第二个数 第三个非0的数开始是第三个数 而且由于需要后两个数相加等于第一个数 可以排除错误可能性

    如果有0的话可以在最前端加0 比如有一个0表示第一个数是0 有两个0表示第二个为0

  • 便秘灵

    表示一开始想到的就是转义

  • 弓弩专卖

    都是牛人啊!羡慕

  • trek jerseys

    这个有些难 不过蛮好的

  • f

    用9进制表示第一个数的位数以9结尾

  • WXY

    奇数位和偶数位各保存一个数字,位数不足前面补0。保存k个数亦同理。

  • caoafei

    用python写了加码和解码。。。拿0做转义符,0用00表示,1用01表示,1作分隔符。果然还是麻烦了,不过写着好玩。。。

    #!/usr/bin/python

    #Encoding is here
    #I will change ‘0’ into ’00’, and ‘1’ into ’01’
    #I will use ‘1’ as the interval

    #Input the 2 numbers
    code1 = str(raw_input(‘Please enter the first code:’))
    code2 = str(raw_input(‘Please enter the second code:’))

    #Calculate the lengths of 2 number strings
    len1 = len(code1)
    len2 = len(code2)

    #Set 2 strings to save the encoded numbers
    code1c = ”
    code2c = ”

    #Encoding the first number
    for i in range(0,len1):
    if code1[i] == ‘0’:
    code1c += ’00’
    elif code1[i] == ‘1’:
    code1c += ’01’
    else:
    code1c += code1[i]

    #Encoding the second number
    for i in range(0,len2):
    if code2[i] == ‘0’:
    code2c += ’00’
    elif code2[i] == ‘1’:
    code2c += ’01’
    else:
    code2c += code2[i]

    #Combine the encoded numbers
    codeFinal = code1c + ‘1’ + code2c

    print codeFinal

    #Here comes the decoding.

    #Set saving spaces
    decoded = ”
    decoded1 = ”

    #Decoding process
    running = 1
    i = 0
    while running:
    if codeFinal[i] == ‘0’:
    if codeFinal[i+1] == ‘0’:
    decoded += ‘0’
    else:
    decoded += ‘1’
    i = i+1
    elif codeFinal[i] == ‘1’:
    decoded1 = decoded
    decoded = ”
    else:
    decoded += codeFinal[i]
    if i == len(codeFinal)-1:
    running = 0
    i = i+1

    decoded2 = decoded

    print decoded1,decoded2

  • cndenis

    计算机用0和1都可以实现对任何信息进行编码,有10个数字应该更容易做了,照套用就好了。

    这个回复系统很不适合发python代码啊,没有缩进,python就残废了,博主想想办法?……

  • cervelo

    ,可以在数字串前设定一个位数足够的数(例如前5位数)来说明数字串要在哪里分开。

  • CodeFarmer2001

    我有一种想法:接着标出字符长度的思路走:
    ·若第一个数很长,则将其9位9位地分开,比如123456789987654=9(123456789)+6(987654)。
    然后把括号去掉,变成91234567896987654。
    假设第二个数是x,那么在刚才生成的字符串后用0隔开:912345678969876540x。

发表评论




Enter Captcha Here :