动态ASCII编码器!


16

介绍

如今,某些ASCII字符是如此昂贵……

为了省钱,您决定编写一个程序,使用便宜的字符对昂贵的字符进行编码。

但是,字符价格经常变化,您不想每次需要编码或解码不同字符时都修改程序!您将需要一个更加动态的解决方案。

挑战

您的任务是编写两个程序:编码器解码器

编码器应该接受五个廉价字符的列表,以及一个昂贵的字符。

它应该输出由廉价字符组成的单个字符串,该字符串对昂贵的字符进行编码。

为了保持价格便宜,该字符串不得超过4个字符。但是,不必在编码中使用所有便宜的字符,并且编码的长度可以不同。


解码器应该接受由编码器输出的字符串,并输出昂贵字符。

除编码字符串外,解码器不接受任何输入。对于任何(有效)输入组合,它都必须在编码器的输出上未经修改地工作。换句话说,您的解码器程序 不知道哪个字符昂贵或便宜。

计分

最短的组合代码胜出!

笔记

  • 所有字符都可以是大写字母[A-Z],小写字母[a-z]或数字[0-9]

  • 廉价字符列表将不包含重复项。没有角色会既便宜又昂贵。

  • 编码器和解码器不必使用相同的语言编写,但是可以相同。您可以编写程序或函数。

  • 输入和输出可以采用适合您语言的任何合理格式。

  • 这两个程序可能不会共享任何变量或数据。

摘要

  • 一些便宜的字符和昂贵的字符的输入被提供给编码器。

  • 编码器输出一串便宜的字符,对昂贵的字符进行编码。

  • 给解码器编码器的输出,并输出昂贵的字符。

例子

输入:     a, b, c, d, e     f

编码器的可能性:     a     eeee     caec

解码器:     f


输入:     a, b, c, d, e     h

编码器的可能性:     bc     cea     eeaa

解码器:     h


输入:     q, P, G, 7, C     f

编码器的可能性:     777     P7     PPCG

解码器:     f


这真的可能就是我,如果是这个问题,我会道歉,但是您应该如何用便宜的字符编码您的信息呢?为5个便宜的字符添加ASCII码?实际上,这个问题仅取决于您的解码器是否必须对生成的所有编码可能性进行解码。
科尔2015年

需要说明的是:编码器可能性仅仅是示例,我们可以根据需要对每个字符进行编码,是吗?
丹尼斯2015年

@丹尼斯是的,这些只是示例。
jrich

@Cole在不放弃实际算法的情况下,这是这里的主要挑战,我相信这是可能的。根据A239914,只有62种可能的昂贵字母可以编码,并且使用这4个ascii字符最多可以编码92个字母。(非常感谢PhiNotPi对此内容的沙盒评论-我没有确切计算出可以编码多少个)
jrich

@UndefinedFunction我现在意识到您的意图:Dennis的问题回答了我的困惑。
2015年

Answers:


5

Pyth,46个字节

编码器,22字节

@smfql{Td^<Szd4S4-Cw48

解码器,24字节

C+48xsmfql{Td^<sS{zd4S4z

哇,很合身。75个不同的字符组合和75.炭范围
Jakube

我想你可以替换S4使用T,并在这两个程序保存每一个字节。
Jakube 2015年

7

CJam,55 50 48 47字节

编码器,24 22 21字节

l$:L4m*{$L|L=},rc'0-=

在线尝试。

解码器,31 28 27 26字节

4_m*{$4,|4,=},l_$_|f#a#'0+

在线尝试。


您使用的是CJam语法表吗?在sourceforge上的那个和其他pdf备忘单没有包含您使用的所有字符,例如'
Luminous

'不是运算符。您可以在语法页面上找到它。
丹尼斯

4

gawk,163 + 165 = 328

在gawk 4.1.1上进行了测试,但也应在较早的gawk版本中工作。需要稍作修改(加长)才能与mawk一起使用。

编码器(163):

{for(gsub(", ",_);sprintf("%c",++r)!=$NF;asort(a))split($1,a,_);r-=r>64?53:46;for(k=4^5;r-=_~i;j=_)for(i=++k;gsub(++j,_,i);)split(k,b,_);for(j in b)printf a[b[j]]}

解码器(165):

{split($1,a,_);for(i in a)d[a[i]]=a[i];asort(d);for(k=4^5;c!~$1;x+=_~i){i=++k;for(c=j=_;gsub(++j,_,i);split(k,b,_));for(g in b)c=c d[b[g]]}printf"%c",x+(x>10?54:47)}

是的,它可以工作,但是我知道这可能不是最好的方法。我不知道第五个廉价字母是什么意思,因为我只使用了四个。

这些仅用于单次使用。如果要输入第二个代码,则必须重新启动它们。输入中需要使用逗号后的空格进行编码。

我的想法

我的第一个问题是“解码器从这四个字符中能得到什么?” (我将它们称为a,b,c和d),最初的想法是从以下关系中获取6位信息:

a>b
a>c
a>d
b>c
b>d
c>d

哇,6位,太完美了!我以为是天才,但测试表明这行不通。只有24种可能的组合。该死的。

下一步是根据我已经知道的内容尝试计算。因此,出现在字符串中的第一个字母将变为0,然后出现在字符串中的第二个字母将变为1,依此类推。但这并不能带我达到所需的62种组合。

0000
0001
0010
0011
0012
0100
0101
0102
0110
0111
0112
0120
0121
0122
0123

但是我还是喜欢这个主意。

好吧,然后让我吃惊的是,我可以将这两者结合起来,因为输入中的字符已经具有关联性,而我不必等到引入它们来给它们赋值时才开始。

怎么运行的

注意:这不再是高尔夫球版本的工作原理,但原理保持不变。

对于解码器:

构造一个数组,其索引包含所有四位数,其最大位数不大于该位数中的不同位数。有75个满足该条件的四个数字。我蛮力地使用它们,因为到目前为止我还无法找到一种构造它们的方法,而且我不确定这在awk中会更短一些。当我找到这些字符时,我按字母顺序将它们分配给了昂贵的字符。

然后,我用数字替换输入字符串中的每个字符。最小的(例如,“ B”小于“ a”)变为1,第二个最小变为2,依此类推,直到4。当然,这取决于输入中有多少个不同的字符,输入的最高位数是多少。结果字符串将是。

然后,我简单地打印具有该字符串作为索引的数组元素。

编码器将相应地工作。

如何使用

直接在awk bash行命令中复制代码,或制作两个文件“ encode.awk”和“ decode.awk”并相应地粘贴代码。甚至更好地使用以下代码,该代码在编码/解码后自动退出,或者可以通过删除结尾的退出命令来多次使用。

编码.awk

{
    if(!x) # only do first time
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:0)++a[p];
            length(a)>=m&&i!~0?c[(x>9?55:48)+x++]=i:_
        }
    r=u=_; # clear reused variables 
    for(gsub(",",FS);sprintf("%c",++r)!=$NF;); # more flexible concerning
    --NF;                                      # spaces in input
    split($0,b);
    asort(b);
    split(c[r],a,_);
    for(j in a)u=u b[a[j]]; # prettier printing than golfed version
    print u
    exit # <=== remove to encode input file
}

解码.awk

{
    if(!x) # only do first time 
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:_)++a[p];
            length(a)>=m&&i!~0?c[i]=sprintf("%c",(x>9?55:48)+x++):_
        }
    delete t; delete d; o=_; # clear reused variables 
    split($1,a,_);
    for(i in a)t[a[i]]=1;
    for(i in t)d[++y]=i;
    asort(d);
    for(i in a)for(j in d)if(d[j]~a[i])o=o j;
    print c[o]
    exit # <=== remove to encode input file
}

这是一个用法示例:

me@home:~/$ awk -f encode.awk
w, 0, R, 1, d X
10R1
me@home:~/$ awk -f decode.awk
10R1
X

请记住,如果使用高尔夫球版本,则每个逗号后都需要空格。

如果需要,可以使用这个简短又脏的脚本来生成一些样本数据

BEGIN{
    for(srand();i++<1000;)
    {
        erg="";
        for(j=0;j++<5;)
        {
            while(erg~(a[j]=substr(c="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",rand()*62+1,1)));
            erg=erg a[j]
        }
        print a[1]", "a[2]", "a[3]", "a[4]", "a[5](rand()>.5?" ":rand()>.5?"  ":"   ")substr(c,rand()*62+1,1)
    }
}

做一些有趣的事情

me@home:~/$ awk -f gen.awk|awk -f encode.awk|awk -f decode.awk|sort -u|wc -l
62

我更多地将其视为编程难题。我觉得有点遗憾,因为这里几乎所有内容都是高尔夫球,因为您可以从有据可查的可读代码中学到更多东西,但这只是我的观点。我按照要求打了高尔夫球;)


怎么测试呢?请分享一些例子。
Shravan Yadav 2015年

+1很棒的解释!似乎有很多方法可以解决这个问题:)
jrich

1
这与我的思考过程非常相似,除了我没有意识到强行强制使用独特的弱组合(您在其中描述的最大位数不大于位数)是一种可行的方法。继续前进的荣誉。
帕特里克·罗伯茨
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.