Telegraphy Golf: Decode Baudot Code

31

fundo

Em 1870, Émile Baudot inventou o Baudot Code , um caractere de comprimento fixo que codifica para telegrafia. Ele projetou o código a ser digitado a partir de um teclado manual com apenas cinco teclas; dois operados com a mão esquerda e três com a direita:

Teclado Baudot de 5 teclas

Os indicadores direito, médio e dedo anelar operam as teclas I , II e III , respectivamente, e o indicador esquerdo e dedo médio operam IV e and . (Doravante, usarei os algarismos arábicos ocidentais, ou seja , de 1 a 5. ) Os caracteres são inseridos como acordes. Para inserir a letra "C", por exemplo, o operador pressiona os botões 1 , 3 e 4simultaneamente, quando um braço rotativo da escova lê cada tecla em sequência e transmite uma corrente ou, para teclas não pressionadas, nenhuma corrente. O resultado é, em termos modernos, uma codificação binária de 5 bits com o mínimo menos significativo, na qual nosso exemplo "C" é codificado como 10110.

5 bits ??

Você pode estar pensando que 5 bits, que podem expressar no máximo 32 símbolos únicos, não são suficientes para todas as letras e números em inglês, para não dizer pontuação. Baudot tinha um truque na manga: seu conjunto de caracteres é na verdade dois conjuntos distintos: Letras e Figuras , e ele definiu dois códigos especiais para alternar entre eles. O deslocamento de letra , que alterna para o modo de letras, é ativado pressionando apenas a tecla 5 ( 00001) e o deslocamento de figura é ativado com a tecla 4 ( 00010).

Desafio

Seu desafio é escrever um programa ou função que decodifique as transmissões do código Baudot.

Uma transmissão real começaria com alguns bits de inicialização, mais um bit de início e parada antes e depois de cada caractere, mas vamos pular esses e nos preocupar apenas com os 5 bits únicos para cada caractere. Os formatos de entrada e saída são discutidos abaixo.

Código de Baudot

Existem duas versões diferentes do Código Baudot: Continental e Reino Unido. Vamos usar a versão do Reino Unido, que não inclui caracteres como "É" do francês nativo de Baudot. Também vamos deixar de fora todos os símbolos da versão do Reino Unido que não estão entre os caracteres ASCII imprimíveis. Você só precisará decodificar os caracteres na tabela abaixo, todos os caracteres ASCII imprimíveis, exceto os três caracteres finais de controle explicados abaixo da tabela.

A coluna "Ltr" mostra os caracteres no modo Letter e "Fig" mostra os caracteres no modo Figure:

        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

As últimas três linhas na coluna da direita são caracteres de controle:

  • ERé apagamento . As máquinas de telegrafia de Baudot imprimiam um símbolo semelhante a um asterisco para esse personagem para dizer ao leitor que o caractere anterior deveria ser ignorado, mas seremos ainda mais agradáveis ​​com o leitor e na verdade omitimos (não imprima) o caractere anterior . Ele age da mesma forma nos modos Letra e Figura.

  • FSé a mudança de figura . Isso muda o conjunto de caracteres de letras para figuras. Se o decodificador estiver no modo Figura, o FS será tratado como um Espaço (logo SPna coluna "Ltr"). Quando o decodificador está no modo Figura, ele permanece no modo Figura até que um caractere LS seja recebido.

  • LSé o deslocamento da letra . Muda o conjunto de caracteres de Figuras para Letras. Se o decodificador já estiver no modo Letter, LS será tratado como um espaço . Quando no modo Letter, o decodificador permanece no modo Letter até que um caractere FS seja recebido.

O decodificador sempre inicia no modo Letter.

Aqui está um exemplo com deslocamento de figura, deslocamento de letra e espaço:

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

Isso gera a mensagem MAY 15TH. Como você pode ver, o primeiro caractere 00001(deslocamento / espaço da letra) atua como um espaço, porque o decodificador já está no modo Letter. O próximo caractere 00010(Mudança de figura / espaço) alterna o decodificador para o modo Figura para imprimir 15. Em seguida, 00001aparece novamente, mas desta vez ele age como Letter Shift para colocar a parte de trás do descodificador no modo Letter.

Para sua conveniência, eis os caracteres em um formato que talvez seja mais fácil de digerir em um editor, classificado por código:

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

Entrada

A entrada será uma sequência de caracteres, matriz ou lista de bits na primeira ordem de bits menos significativa. Cada caractere será representado por um quinteto de 5 bits. Os bits podem ser em qualquer formato razoável, por exemplo, uma cadeia binária, uma matriz de 0s e 1s, de uma cadeia "0"e "1" caracteres, um único número muito grande, etc, contanto que mapeia directamente para os bits de transmissão.

Toda transmissão terá pelo menos um quinteto imprimível e no máximo 255 quintetos (imprimíveis ou não), ou seja, de 5 a 1.275 bits, inclusive.

A entrada pode conter apenas os bits da transmissão, com duas exceções permitidas: qualquer número de 0bits iniciais ou finais e / ou, para entrada de sequência, uma única nova linha final pode ser adicionada à transmissão. Os bits ou caracteres iniciais ou finais não podem ser adicionados antes ou depois de cada quinteto, ou seja, você não pode aumentar cada quinteto para 8 bits (ou considerar cada quinteto como um número único em uma matriz - a menos que seu idioma tenha um tipo inteiro de 5 bits) ou separado quintetos com quaisquer bits adicionais, por exemplo "01111\n11100".

Notas e estojos

  1. A transmissão conterá apenas os caracteres nas colunas "Ltr" e "Fig" na tabela acima. Você nunca receberá, por exemplo, 01110no modo Figura, porque está ausente na coluna "Fig".

  2. Supõe-se que o decodificador esteja sempre no modo Letter no início de uma transmissão. No entanto, o primeiro caractere pode ser um caractere FS para alternar para o modo Figura imediatamente.

  3. Quando o decodificador está no modo Letter, ele pode receber um caractere LS e, no modo Figura, ele pode receber um caractere FS. Em qualquer um dos casos, um caractere de espaço deve ser impresso (consulte Saída).

  4. O caractere ER nunca será o primeiro caractere de uma transmissão, nem seguirá imediatamente um LS, FS ou outro ER.

  5. Um personagem FS pode seguir imediatamente um personagem LS e vice-versa.

  6. Nem o caractere LS nem o FS serão o último caractere em nenhuma transmissão.

  7. Os caracteres /e -podem ser recebidos no modo Letter (códigos 11000e 10001, respectivamente) ou no modo Figura ( 10111 e 00111).

Saída

A saída pode estar em qualquer formato razoável, sendo o mais razoável ASCII (ou UTF-8, para o qual todos os caracteres representados são iguais a ASCII). Indique na sua resposta se a sua saída está em outra codificação ou formato.

Notas

  • O caractere de espaço (veja 3. acima) deve ser um espaço ASCII (0x20) ou o equivalente da sua codificação, ou seja, o que você obtém ao pressionar a barra de espaço.

Ganhando

Isso é . O código mais curto em bytes vence.

Restrições

  • As brechas padrão são proibidas.

  • Espaços à direita e / ou uma única nova linha à direita são permitidos. Espaços iniciais ou outros caracteres (que não fazem parte da transmissão) não são permitidos.

  • Você não pode usar nenhuma função interna ou de biblioteca que decodifique o Baudot Code (ou qualquer um de seus descendentes, por exemplo, Murray Code, ITA-1, etc.).

Casos de teste

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):     -/=/-
Jordânia
fonte
Relacionado.
Jordânia
1
Nota: codifiquei os casos de teste manualmente; se vir algo que parece errado, fale.
Jordânia
1
Na tabela de códigos e no resumo que o acompanha, o código 00010é listado como SPno modo de letra e FSno modo de figura. De acordo com a descrição, se estamos no modo de letra e recebemos código 00010, devemos mudar para o modo de figura, mas os valores na tabela parecem ser o contrário. Além disso, vice-versa para 00001.
Sok
3
Esse homem era muito esperto, eu nunca soube da compressão usada na telegrafia. Obrigado pela aula de história, cara.
Magic Octopus Urn
4
@carusocomputing Direito ?? Baudot não tinha educação formal além da escola primária, mas não apenas inventou o Código Baudot, como também inventou um sistema de multiplexação que permitia que quatro operadores usassem uma única linha de telégrafo simultaneamente. Achei este panfleto de 1919 que descreve suas invenções com alguns detalhes super interessantes: samhallas.co.uk/repository/telegraph/b6_baudot_multiplex.pdf
Jordan

Respostas:

6

Pitão, 98 97 95 93 90 83 80 bytes

O código contém caracteres não imprimíveis, então aqui está um xxdhexdump reversível :

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

Experimente online. Suíte de teste.

Bastante longo, mas a tabela de pesquisa ocupa quase metade do espaço.

Para 117 bytes, eis a mesma coisa sem imprimíveis (embora seja necessário o 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

Ou, para 93 bytes, sem compactação na tabela de pesquisa:

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

JavaScript (ES6), 160 158 153 bytes

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"));

Arnauld
fonte
5

Lote, 306 304 bytes

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

Recebe entrada em STDIN. Como o Lote não possui conversão binária, eu tenho que falsificá-lo usando a conversão octal e hexadecimal.

  • Os dois primeiros dígitos são convertidos de octal (não posso usar decimal porque o primeiro dígito pode ser 0). Os valores possíveis são 00, 01, 10e 11. Os dois últimos têm valor 8e, 9mas eu quero 2ou 3então tomo o módulo restante 6.
  • Os últimos três dígitos são convertidos de hexadecimal. Os dígitos são 14ou 252multiplicados pelo valor desejado, para eu pegar o restante do módulo 14( 252=14*18).
  • c é a sequência codificada
  • r é o resultado até agora
  • d é a matriz de decodificação
  • s é o índice (levando em consideração o estado do turno) do caractere que alterna o estado do turno
  • né a decodificação binária mais o bit 5 de s, que é igual ao estado de mudança; nesse caso, o estado de mudança é alternado ou indexa a matriz de decodificação para encontrar o próximo caractere (ou! para apagar)
Neil
fonte
3

PHP, 206 bytes

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);
Jörg Hülsermann
fonte
2

Chip , 1069 bytes

É um grande sucesso, mas foi bastante divertido de escrever.

Recebe a entrada como uma sequência de "1"'s e "0"' s. (Embora realmente apenas analise um pouco.)

 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

Experimente online!

Nota: O Erasure usa o caractere de backspace ASCII ( \x08), o que significa que eles ficarão engraçados no TIO, mas ficarão bem, digamos, no xterm.

Estrutura básica

No topo, acima da =linha, está o decodificador de entrada. Transforma a entrada em um dos 32 sinais separados. Eles são enviados dos oacima =para os abaixo.

As montanhas triangulares de L'e R' apenas rotacionam o padrão de linhas separadas para colunas. A grade abaixo que traduz cada coluna em seu caractere de saída. Para sinais desconhecidos, NUL ( \x00) é produzido. Para os turnos especiais, em vez de imprimir um caractere, o pequeno blob à direita altera o modo.

O teleférico entre as duas montanhas suprime qualquer impressão entre cada quinteto; caso contrário, isso também tentaria decodificar todos os quintetos sobrepostos. Tente substituir o !por um espaço para ver isso por si mesmo. (A execução no modo detalhado -vtambém pode ser interessante aqui.)

Não tenho certeza de como fazer isso menor no momento; já é bastante denso por seu tamanho.

Phlarx
fonte
0

GNU sed, 334 + 1 = 335 bytes

+1 byte para -rsinalizador. Recebe entrada em STDIN.

Olhando para os velhos desafios, percebi que esse seria muito fácil com o sed e bom para a prática. Como não tentei compactação, a tabela de pesquisa é mais da metade do código.

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

Experimente online!

Explicação

O código funciona em duas fases: primeiro, ele substitui cada execução de 5 dígitos binários pelos dois caracteres correspondentes (letra e figura) de uma tabela de pesquisa. A tabela de pesquisa está no formato 𝟎𝟎𝟎𝟎𝟎𝐋𝐅𝟎𝟎𝟎𝟎𝟎𝐋𝐅… onde 𝟎 é um dígito binário e 𝐋 e 𝐅 são a letra e o número correspondentes, respectivamente. %significa caracteres ausentes (pode ser qualquer caractere que não seja nova linha). FS/SPé representado por f<space>e SP/LSé <space>l. ERé representado por <<.

Em seguida, percorre cada par com um "cursor" correspondente ao modo atual - para o modo #de letra, @para o modo de figura. O #cursor remove o segundo caractere do par e depois avança para o próximo par, e o @remove o primeiro e avança. Em outras palavras, #A1B8torna A#B8- se e então AB#, e @A1B8torna 1@B8- se e então 18@. Quando o #cursor encontra, f<space>ele o exclui e se substitui pelo @cursor, e vice-versa, quando o @encontra <space>l.

Quando nenhum par permanece, o cursor final é removido junto com os caracteres seguidos por <.

# 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.
Jordânia
fonte