解决对角Burrows-Wheeler变换


11

介绍

在此挑战中,您将解决对角线Burrows-Wheeler变换。这是什么是对角Burrows-Wheeler变换的一般概述。要对消息进行编码,必须首先确保其长度为奇数(即5、7、9等)。然后,n通过来构建网格,n其中n消息的长度在哪里。第一行是原始消息。此后的每一行都是其上方的一行,但向左移动了1个字符,第一个字符向后移动。例如:

Hello World
ello WorldH
llo WorldHe
lo WorldHel
o WorldHell
 WorldHello
WorldHello 
orldHello W
rldHello Wo
ldHello Wor
dHello Worl

然后,将NW到SE对角线上的每个字母放入一个新字符串中:

Hello World  H
ello WorldH  l
llo WorldHe  o
lo WorldHel  W
o WorldHell  r
 WorldHello  d
WorldHello   e
orldHello W  l
rldHello Wo  (space)
ldHello Wor  o
dHello Worl  l

您的编码信息是HloWrdel ol。要进行解码,请先获取编码后的消息的长度,再加1,然后除以2 x。现在我们知道x,从第一个字母开始,每个字母都x在最后一个字母之后,然后循环。例如:

H   l   o   W   r   d   e   l     o   l
1   

Then...

H   l   o   W   r   d   e   l     o   l
1                       2

And again...

H   l   o   W   r   d   e   l     o   l
1   3                   2

Until you get...

H   l   o   W   r   d   e   l       o   l
1   3   5   7   9  11   2   4   6   8  10

现在,只需按照正确的顺序重新排列字母即可Hello World

挑战

您面临的挑战是编写两个程序,函数或其中之一。但是,两者必须使用相同的语言。第一个程序将接受通过STDIN输入的字符串,程序参数或函数参数,并使用此方法对其进行编码。第二个程序将接受通过STDIN输入的字符串,程序参数或函数参数,并使用此方法对其进行解码

要求

第一个程序/功能

  • 使用上面列出的任何方法输入的单个字符串。
  • 必须使用对角线Burrows-Wheeler转换样式对字符串进行编码。

第二程序/功能

  • 使用上面列出的任何方法输入的单个字符串。
  • 必须使用对角线Burrows-Wheeler转换样式对字符串进行解码。

约束条件

  • 您不能使用任何内置或外部功能来完成此任务。
  • 不允许出现标准漏洞。
  • 两个程序/功能必须使用相同的语言。

计分

这是代码高尔夫球,因此以字节为单位的最短程序获胜。

如果我需要添加更多信息,请发表评论!


2
我们是否必须将偶数长度的输入字符串转换为奇数长度?
Optimizer

5
这不是Burrows-Wheeler变换。
FUZxxl 2015年

3
Burrows-Wheeler变换的不同之处在于,所有旋转的数组都按照字典顺序进行排序,然后再取最后一个项目。
FUZxxl 2015年

@Optimizer没必要。
GamrCorps,2015年

Answers:


12

CJam(4 + 8 =)12个字节

编码程序:

q2/z

在这里在线尝试

解码程序:

q_,2/)/z

在这里在线尝试

它们如何(或更确切地说,为什么)工作

对角Burrows-Wheeler变换基本上是字符串的所有其他字符,并从末尾进行换行。如果我们将String视为2列的2D矩阵,则可以简单地归结为对矩阵进行转换。例:

Hello World

表示为2D矩阵为

He
ll
o 
Wo
rl
d

现在,只需按列阅读即可,给出:

HloWrdel ol

这就是Burrows-Wheeler变换。

解码与该过程完全相反,将字符串写入2行2D矩阵并逐列读取。

代码扩展

编码器:

q          "Read the input";
 2/        "divide it into sub arrays of 2 characters";
   z       "Take transform";

解码器:

q_,        "Read the input, take copy and get length of copy";
   2/      "Divide the length by 2";
     )/    "Increment and split the input into two rows";
       z   "Take transform";

7

Python 2,61字节

E=lambda x:x[::2]+x[1::2]
D=lambda y:(-~len(y)/2*y)[::len(y)/2+1]

E加密和D解密。我没有计算得分的E=D=

解密将每个n第'个字符环绕起来,其中n字符串长度的一半向上舍入。之所以取反,是因为它2n字符串的长度取模,所以取n第一个字符取反取第一个字符2

如果允许使用单个功能,我可以做44个字节

def F(x,b):n=1+len(x)**b>>b;return(n*x)[::n]

该加密时bFalse当解密bTrue。表达式1+len(x)**b>>b等于[2,len(x)/2+1][b]


4

J,10 + 10 = 20

   ({~#|2*i.@#) 'Hello World'
HloWrdel ol

   (/:#|2*i.@#) 'HloWrdel ol'
Hello World

(环绕括号不是函数定义的一部分,因此不计入分数。)

感谢FUZxxl对3字节的改进。

现在很好地显示了这两个函数是相反的,因为第一个函数从列表定义的位置获取字符,#|2*i.@#第二个函数使用与排序相同的列表重新排列字符。

在这里在线尝试。


第一个也可以用10个字符完成:{~#|2*i.@#
FUZxxl 2015年

@FUZxxl谢谢,更新。现在,很好地显示了两个函数之间的关系。
randomra

3

Pyth-5 + 11 = 16个字节

我注意到一个模式!〜跳舞愉快吗〜转换实际上只是循环遍历字符串并选择其他所有元素。它只能在奇数上工作,因为否则它将永远不会获得一半的元素。这等效于旋转2宽的矩阵。

编码器:

%2*2z

Python的步骤切片不会循环,因此我重复了该字符串。

%2      Take every other elements
 *2z    Double input string

解码器:

K/hlz2%K*Kz

再次没有逐步切片的环绕。

K/hlz2       K=length of (input+1)/2
%K           Every kth element
 *Kz         From K*the input

@FryAmTheEggman我很确定它只应该采用奇数长度的字符串。它是在描述的开始。
Maltysen,2015年

哎呀,对不起。:S
FryAmTheEggman 2015年

2

GNU sed -r,(20 + 104 + 1)= 125

乐谱中额外的+1是用于-r选项的。假定为奇数长度的输入字符串。

编码器:

s/.*/&&/
s/(.)./\1/g
  • 加倍输入字符串
  • 删除每个奇数(从1开始计数)字符

解码器:

解码器将其:用作临时标记字符,因此,如果它出现在输入字符串中,则会出现不确定的行为。如果输入字符串限制为95个ASCII字符,则可以用ASCII范围以外的内容(例如BEL 0x7)替换这些标记,以解决此问题。

s/.*/:&:/
:l;s/:(.)(.+)(.):/\1:\2:\3/;tl
s/:(.*)/\1:/
:m;s/(.)(.*):(.?)(.*):(.*)/\2:\4:\5\1\3/;tm
s/://g
  • :标记放在输入字符串的开头和结尾
  • 一次随机播放第一个:向前和:向后的第二个字符,直到:标记位于中间字符的两侧
  • 删除第一个,::在结尾添加另一个,以留下“ A:B:”,其中A是明文输入中由奇数字符组成的字符串,B是由偶数字符组成的字符串
  • 最后一次:将A和B的字符拼凑在一起以重新组装纯文本输入
  • 删除剩余的 :标记

2

JavaScript ES6,41 + 49 = 90字节

编码器

(t=>t.replace(/./g,(_,o)=>t[o*2%t.length]))('Hello World')

解码器

(t=>t.replace(/./g,(_,o)=>t[-~(l=t.length)/2*o%l]))('HloWrdel ol')

这些是匿名函数,因此我只计算括号内的代码,因为这是整个函数定义。使用以下代码段进行尝试:(已修改为使用ES5)


怎么样:[t=>t.replace(/./g,(_,o)=>t[o*2%t.length]),t=>t.replace(/./g,(_,o)=>t[(1+(l=t.length))/2*o%l])]?您可以像[...][0]('encode string')和一样使用它[...][1]('decode string')。没什么可以说的!然后您保存1个字节。
伊斯梅尔·米格尔

谢谢,但它说要编写2个函数,但我认为这不算什么。
NinjaBearMonkey 2015年

那仍然是两个功能。规则没有指定名称或访问函数的方式。它只是说您必须使用2个功能。
Ismael Miguel

1
@IsmaelMiguel现在我考虑了一下,我认为匿名函数本身是允许的,因此使用它可以节省更多字节。
NinjaBearMonkey

我很高兴您减少了字节数。
Ismael Miguel
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.