电报高尔夫:解码Baudot码


31

背景

ÉmileBaudot在1870年发明了Baudot Code,这是一种用于电报的固定长度字符编码。他设计的代码可以通过仅用五个键的手动键盘输入。两个用左手操作,三个用右手操作:

宝德5键键盘

右手食指,中指和无名指分别操作IIIIII键,左手食指和中指操作 IVⅤ键。(此后,我将使用其西方阿拉伯数字,即 15。)字符作为和弦输入。输入字母“C”,例如,操作者按下13,和4同时,旋转的刷臂依次读取每个按键并传输电流,或者对于未按下的按键,则不传输电流。用现代术语来说,结果是5位最低有效位优先的二进制编码,其中我们的示例“ C”被编码为10110

5位?

您可能会认为,最多可以表示32个唯一符号的5位甚至对于所有英文字母和数字都不够,更不用说标点符号了。不过,鲍多有个绝招:他的字符集实际上是两个不同的集:字母数字,并且他定义了两个特殊的代码在它们之间切换。 仅需5键(00001)即可激活切换到Letters模式的Letter Shift,并用4键()激活 Figure Shift00010

挑战

您面临的挑战是编写一个程序或函数来解码Baudot码传输。

实际的传输将从一些初始化位开始,再加上每个字符前后的开始和停止位,但是我们将跳过这些初始化位,仅担心每个字符的5个唯一位。输入和输出格式在下面讨论。

鲍多密码

有两种不同的Baudot代码版本:Continental和UK我们将使用UK版本,其中包括Baudot的母语法语中的“É”之类的字符。我们还将忽略所有不属于可打印ASCII字符的英国版本的符号。您只需要解码下表中的字符,所有这些字符都是可打印的ASCII字符,下表中说明的最后三个控制字符除外。

“ Ltr”列显示字母模式下的字符,而“ Fig”显示图形模式下的字符:

        Encoding             Encoding
Ltr Fig  12345       Ltr Fig  12345
--- --- --------     --- --- --------
 A   1   10000        P   +   11111
 B   8   00110        Q   /   10111
 C   9   10110        R   -   00111
 D   0   11110        S       00101
 E   2   01000        T       10101
 F       01110        U   4   10100
 G   7   01010        V   '   11101
 H       11010        W   ?   01101
 I       01100        X       01001
 J   6   10010        Y   3   00100
 K   (   10011        Z   :   11001
 L   =   11011        -   .   10001
 M   )   01011        ER  ER  00011
 N       01111        FS  SP  00010
 O   5   11100        SP  LS  00001
 /       11000

右列的最后三行是控制字符:

  • ER擦除。鲍多的电报机会为此字符打印一个星号样的符号,以告诉读者应该忽略前一个字符,但是对于读者来说,我们会变得更好,实际上将省略(不打印)前一个字符。在Letter和Figure模式下,它的作用相同。

  • FSFigure Shift。这会将字符集从字母切换为数字。如果解码器已经处于图形模式,则将FS视为空格SP“ Ltr”列中的ergo )。当解码器处于图形模式时,它将保持图形模式,直到接收到LS字符为止。

  • LSLetter Shift。它将字符集从数字切换为字母。如果解码器已经处于Letter模式,则LS被视为Space。在字母模式下,解码器将保持字母模式,直到接收到FS字符为止。

解码器始终以字母模式启动。

这是一个具有图形移位,字母移位和空格的示例:

01011 10000 00100 00001 00010 10000 11100 00001 10101 11010
  M     A     Y   LS/SP FS/SP   1     5   LS/SP   T     H

这产生消息MAY 15TH。如您所见,第一个00001(字母移位/空格)字符用作空格,因为解码器已经处于字母模式。下一个字符00010(Figure Shift / Space)将解码器切换到Figure模式进行打印15。然后00001再次出现,但是这次将其作为Letter Shift来使解码器返回Letter模式。

为了方便起见,以下是一些字符,其格式可能更容易在编辑器中提取,并按代码排序:

A,1,10000|E,2,01000|/,,11000|Y,3,00100|U,4,10100|I,,01100|O,5,11100|FS,SP,00010|J,6,10010|G,7,01010|H,,11010|B,8,00110|C,9,10110|F,,01110|D,0,11110|SP,LS,00001|-,.,10001|X,,01001|Z,:,11001|S,,00101|T,,10101|W,?,01101|V,',11101|ER,ER,00011|K,(,10011|M,),01011|L,=,11011|R,-,00111|Q,/,10111|N,,01111|P,+,11111

输入值

输入将是字符串,数组或以最低有效位优先顺序排列的位列表。每个字符将由5位五重奏表示。位可以是任何合理的格式,例如一个二进制串,数组0S和1S,的字符串"0""1" 字符,一个单一的数量非常大,等等,只要它直接映射到变速器的比特。

每个传输将至少有一个可打印的五重奏和最多255个(可打印或其他形式的)五重奏,即5至1,275位(含)。

输入可以包含在传输的位,用两个允许例外:任何数量的前缘或后的0比特和/或用于字符串输入,单个结尾的新行可以被添加到变速器。不能在每个五重奏之前或之后添加前导或尾随位或字符,即,您不能将每个五重奏填充到8位(或将每个五重奏作为数组中的一个数字使用-除非您的语言为5位整数类型)或单独具有任何其他位的五重奏,例如"01111\n11100"

笔记和边缘案例

  1. 传输将仅包含上表“ Ltr”和“ Fig”列中的字符。例如01110,您将永远不会收到“ 体形”模式,因为“体形”列中没有它。

  2. 假定解码器在传输开始时始终处于字母模式。但是,第一个字符可能是FS字符,可以立即切换到图形模式。

  3. 当解码器处于字母模式时,它可能会收到一个LS字符,而当它处于图形模式时,它可能会收到一个FS字符。无论哪种情况,都必须打印一个空格字符(请参见输出)。

  4. ER字符永远不会成为传输中的第一个字符,也永远不会紧随LS,FS或另一个ER之后。

  5. FS字符可以紧随LS字符,反之亦然。

  6. LS和FS字符都不是任何传输中的最后一个字符。

  7. /-字符可以以字母模式(代码被接收1100010001,分别地)或图模式(1011100111)。

输出量

输出可以是任何合理的格式,最合理的是ASCII(或UTF-8,所有表示的字符都与ASCII相同)。请在您的答案中指出您的输出是否为其他编码或格式。

笔记

  • 空格字符(请参见上面的3.)应为ASCII空格(0x20)或等效的编码,即按空格键时得到的内容。

获奖

这是。以字节为单位的最短代码获胜。

限制条件

  • 禁止出现标准漏洞。

  • 允许尾随空格和/或单个尾随换行符。不允许前导空格或其他字符(不属于传输的一部分)。

  • 您不得使用任何内置或库函数来解码Baudot代码(或其任何后代,例如Murray代码,ITA-1等)。

测试用例

Input: 001101000010100111101110010101
Output: BAUDOT
Input: 11010010001001100011110111101111100
Output: HELLO
Input: 01011100000010000001000101000011100000011010111010
Output: MAY 15TH
Input: 0001000100010000001000001011101110011100101010010110101010001111100101
Output: 32 FOOTSTEPS
Input: 10110000110101011100111100001111011010000001101110
Output: GOLF
Input: 000100011000001111100000100010110111001100010110010000111111
Output: 8D =( :P
Input: 0000100001000010000100010001111011111011000011100010001
Output (4 leading spaces):     -/=/-


1
注意:我手动编码了测试用例;如果您发现任何看起来不对的地方,请说出来。
乔丹

1
在代码表和随附的摘要中,代码以字母模式和图形模式00010列出。根据描述,如果我们处于字母模式并且收到代码,则应该切换到数字模式,但是表中的值似乎与之相反。同样,反之亦然。SPFS0001000001
Sok 2016年

3
这个人真是太聪明了,我从来不知道电报中使用的压缩技术。感谢您的历史课。
魔术章鱼缸

4
@carusocomputing对吗?鲍多(Baudot)小学以后没有接受过正规教育,但他不仅发明了鲍多(Baudot)代码,还发明了一种多路复用系统,允许四名操作员同时使用一条电报线。我发现这本1919年的小册子非常有趣地详细描述了他的发明:samhallas.co.uk/repository/telegraph/b6_baudot_multiplex.pdf
约旦

Answers:


6

Pyth,98 97 95 93 90 83 80字节

该代码包含不可打印的字符,因此这是一个可逆的xxd十六进制转储:

00000000: 753f 7133 4a69 4832 5047 2b47 3f3c 334a  u?q3JiH2PG+G?<3J
00000010: 4040 6332 2e22 275a 75ae 5751 fb4e 3cd7  @@c2."'Zu.WQ.N<.
00000020: 02ce 8719 aac1 e0e0 fe1f 09e5 85bc a767  ...............g
00000030: 8e0c 1f47 508a cad1 1acb b26f 951e e5d6  ...GP......o....
00000040: 225a 4a2a 5c20 715a 3d5a 744a 637a 356b  "ZJ*\ qZ=ZtJcz5k

在线尝试。 测试套件。

很长,但查找表不占用大部分空间的一半。

对于117个字节,这是没有不可打印的内容(不过需要ISO-8859-1):

u?q3JiH2PG+G?<3J@@c2."'Zu®WQûN<×\x02Î\x87\x19ªÁààþ\x1f\tå\x85¼§g\x8e\x0c\x1fGP\x8aÊÑ\x1a˲o\x95\x1eåÖ"ZJ*\ qZ=ZtJcz5k

或者,对于93个字节,在查找表上不进行压缩:

u?q3JiH2PG+G?<3J@@c2"OVDPYSBREXGMIWFNA-JKUTCQ/ZHL5'0+3;8-2;7);?;;1.6(4;9/;:;="ZJ*\ qZ=ZtJcz5k

5

的JavaScript(ES6),160个 158 153字节

let f =
    
s=>s.replace(/.{5}/g,s=>(n='0b'+s-1)<2?m-n?(m^=1,''):' ':"? !YSBREXGMIWFNA-JKUTCQ/ZHLOVDP? ?!3 8-2 7) ?  1.6(4 9/ : =5'0+"[n+m*32],m=0).replace(/.!/g,'')

console.log(f("001101000010100111101110010101"));
console.log(f("11010010001001100011110111101111100"));
console.log(f("01011100000010000001000101000011100000011010111010"));
console.log(f("0001000100010000001000001011101110011100101010010110101010001111100101"));
console.log(f("10110000110101011100111100001111011010000001101110"));
console.log(f("000100011000001111100000100010110111001100010110010000111111"));
console.log(f("0000100001000010000100010001111011111011000011100010001"));


5

批处理,306304字节

@echo off
set/pc=
set r=
set d=! !!YSBREXGMIWFNA-JKUTCQ/ZHLOVDP!! !3!8-2!7)!?!!1.6(4!9/!:!=5'0+
set s=2
:l
set/an=(s^&32)+0%c:~,2%%%6*8+0x%c:~2,3%%%14
set c=%c:~5%
if %n%==%s% set/as^^=35&goto l
call set r=%%r%%%%d:~%n%,1%%
if %r:~-1%==! set r=%r:~,-2%&goto l
if not "%c%"=="" goto l
echo %r%

在STDIN上输入。由于Batch没有二进制转换,因此我必须使用八进制和十六进制转换来伪造它。

  • 前两位数字是从八进制转换的(我不能使用十进制,因为前一位数字可能是0)。可能的值是00011011。后两者具有价值89,但我想2还是3等我取余数模6
  • 最后三位数从十六进制转换。数字是其期望值的倍数14252乘以它们的期望值,以余数取模14252=14*18)。
  • c 是编码字符串
  • r 到目前为止的结果
  • d 是解码数组
  • s 是切换换档状态的字符的索引(考虑换档状态)
  • n是二进制解码加上的第5位s,它等于移位状态(在这种情况下切换状态),或者索引到解码数组中以查找下一个字符(或擦除的是!)

3

PHP,206字节

foreach(str_split($argv[1],5)as$s)($k="# f*YSBREXGMIWFNA-JKUTCQ/ZHLOVDP#l *3#8-2#7)#?##1.6(4#9/#:#=5'0+"[32*$f+bindec($s)])=="*"?array_pop($a):($k=="f"?$f=1:($k=="l"?$f=0:($k=="#"?:$a[]=$k)));echo join($a);

2

芯片,1069字节

这是个很大的东西,但是写起来很有趣。

将输入作为字符串“ "1"”和"0"“”。(尽管它实际上只看低位。)

 AZZZZ,-o.AZZZZ  AZZZZ,o-.AZZZZ
*\\\\\]oo[\/\\\**//\\\]oo[/\\\\*
*\\\\/]oo[\/\\/**//\\/]oo[/\\\/*
*\\\//]oo[\/\//**//\//]oo[/\\//*
*\\\/\]oo[\/\/\**//\/\]oo[/\\/\*
*\\//\]oo[\///\**////\]oo[/\//\*
*\\///]oo[\////**/////]oo[/\///*
*\\/\/]oo[\//\/**///\/]oo[/\/\/*
*\\/\\]oo[\//\\**///\\]oo[/\/\\*
=
        o--------K-----o
      ,oo.   z---+~S  ,oo.
     ,LooR. !ZZZZ'   ,LooR.
    ,LLooRR.        ,LLooRR.
   ,LLLooRRR.      ,LLLooRRR.
  ,LLLLooRRRR.    ,LLLLooRRRR.
 ,LLLLLooRRRRR.  ,LLLLLooRRRRR. ,~Z
,LLLLLLooRRRRRR.,LLLLLLooRRRRRR.>m'
|||||||oo||||||||||||||oo||||||)/Rz.
xxxxxxxxxxxxxxx)xxxxxxxxxxxxxxxx\^-^S
x)x))))))))))))xx)))))))))))))xx\g
xx)xxxxxxxxxxxxxxxxxxxxxxxxxxx))\f
xxxxxx))xxxxxxxxxxxxx)))))))))xx\e
xx)x))x)xxxxx))x)))))xxxxxxx)))x\d
xx))x))xxx)))xxxxx)))xxxx)))xx)x\c
xx)xx)xx))x))x)xx)xx)xx))x))x)xx\b
x)))))))x)xx)xxxx)x)xx)x)xx)xx)x\a
x)x)x))))))x)x))x)))x)))xx))x))x/f
x)x)x))))))x)x)xxx)xxxxxxxx)x)xx/e
xxxxxxxx))xxxxxx))))x)))xxx)x))x/d
xxxxx))xxxxx)x)xxx)xxx))xx))xx)x/c
xxx)xxx)xxxx)x)xxxxxx))xxx))x))x/b
x)xxx)x)x)xx)xxxxx))x)))xx))xxxx/a

在线尝试!

注意:Erasure使用ASCII退格字符(\x08),这意味着它们在TIO中看起来很有趣,但是在xterm中看起来很好。

基本结构

在该行上方的顶部=是输入解码器。它将输入转换为32个独立信号之一。这些是从o的上方发送=到下方的。

Ls和的三角山脉R只是将模式从单独的行旋转到列。下面的网格将每一列转换为其输出字符。对于未知信号,\x00将生成NUL()。对于特殊班次,右侧的小斑点代替了打印字符,而是更改了模式。

两座山之间的缆车之类的东西抑制了每个五重奏之间的任何打印,否则,这也会尝试对所有重叠的五重奏进行解码。尝试将其替换!为空格以自己查看。(在-v此处以详细模式运行也可能很有趣。)

我不确定目前如何缩小尺寸;它的大小已经很密集了。


0

GNU sed,334 + 1 = 335字节

+1字节的-r标志。在STDIN上输入。

回顾过去的挑战,我意识到使用sed可以很容易地完成这一挑战,并且对实践很有帮助。我没有尝试任何压缩,因此查找表超过一半的代码。

s|.*|#@&;01000E211000/%00100Y310100U401100I%11100O500010f 10010J601010G711010H%00110B810110C901110F%00001 l10001-.01001X%11001Z:00101S%10101T%01101W?11101V'00011<<10011K(01011M)11011L=00111R-10111Q/01111N%11111P+10000A111110D0|
:
s/@([01]{5})(.*;.*\1)(..)/\3@\2\3/
t
s/@;.*//
s/#f /@/
s/@ l/#/
s/#(.)./\1#/
s/@.(.)/\1@/
t
s/.<|[#@]//g

在线尝试!

说明

该代码分两个阶段工作:首先,它用查询表中相应的两个字符(字母和数字)替换5位二进制数字的每次运行。查找表的格式为𝟎𝟎𝟎𝟎𝟎𝐋𝐅𝟎𝟎𝟎𝟎𝟎𝐋𝐅…,其中𝟎是二进制数字,𝐋和𝐅分别是对应的字母和数字。%代表缺少的字符(这可能是换行符以外的任何字符)。FS/SPf<space>SP/LS表示<space>lER以表示<<

然后,它通过与当前模式相对应的“光标”(#用于字母模式,@用于图形模式)遍历每一对。该#光标去除了对第二个字符,然后前进到下一个对,并且@移除第一和进展。换句话说,#A1B8变为A#B8,然后AB#@A1B8变为1@B8,然后18@。当#光标遇到f<space>它删除它,并用自身替换@光标,反之当@遇到<space>l

如果没有剩余的对,则最后的光标以及所有字符和其后的都将被删除<

# Setup: Append a lookup table to the line.
# Also prepends "#" and "@" which we'll use as "cursors" later.
s|.*|#@&;01000E211000/%00100Y310100U401100I%11100O500010f 10010J601010G711010H%00110B810110C901110F%00001 l10001-.01001X%11001Z:00101S%10101T%01101W?11101V'00011<<10011K(01011M)11011L=00111R-10111Q/01111N%11111P+10000A111110D0|

# Phase 1
:
  # Using "@" as a "cursor", substitute for each run of 5 binary digits the
  # two corresponding characters from the lookup table.
  s/@([01]{5})(.*;.*\1)(..)/\3@\2\3/
  t   # Loop (branch to `:`) as long as substitutions are made.

s/@;.*//       # Delete the "@" and lookup table

# Phase 2
s/#f /@/       # FS (f ) in letter mode (#); delete and switch to figure mode (@ cursor).
s/@ l/#/       # LS ( l) in figure mode (@); delete and switch to letter mode (# cursor).
s/#(.)./\1#/   # Letter mode; replace pair with first of pair; advance cursor.
s/@.(.)/\1@/   # Figure mode; replace pair with second of pair; advance cursor.
t              # If any substitutions were made, branch (loop) to `:`.

# Teardown
s/.<|[#@]//g   # Delete characters followed by < (ER) and cursor.
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.