Telegraphy Golf: Decode Baudot Code

31

Fondo

En 1870, Émile Baudot inventó el Código Baudot , una codificación de caracteres de longitud fija para telegrafía. Diseñó el código para ingresarlo desde un teclado manual con solo cinco teclas; dos operados con la mano izquierda y tres con la derecha:

Teclado Baudot de 5 teclas

Los dedos índice derecho, medio y anular operan las teclas I , II y III , respectivamente, y los dedos índice y medio izquierdos operan IV y . (De ahora en adelante usaré sus números arábigos occidentales, es decir , del 1 al 5 ). Los caracteres se ingresan como acordes. Para ingresar la letra "C", por ejemplo, el operador presiona 1 , 3 y 4teclas simultáneamente, con lo cual un brazo de cepillo giratorio lee cada tecla en secuencia y transmite una corriente o, para las teclas no presionadas, no hay corriente. El resultado es, en términos modernos, una codificación binaria de primer bit menos significativo de 5 bits, en la que nuestro ejemplo, "C", se codifica como 10110.

5 bits ??

Quizás esté pensando que 5 bits, que pueden expresar a lo sumo 32 símbolos únicos, no son suficientes para todas las letras y números en inglés, por no mencionar la puntuación. Sin embargo, Baudot tenía un truco bajo la manga: su conjunto de personajes es en realidad dos conjuntos distintos: letras y figuras , y definió dos códigos especiales para cambiar entre ellos. El cambio de letras , que cambia al modo de letras, se activa presionando solo la tecla 5 ( 00001), y el cambio de figuras se activa con la tecla 4 ( 00010).

Reto

Su desafío es escribir un programa o función que decodifique las transmisiones de Código Baudot.

Una transmisión real comenzaría con algunos bits de inicialización, más un bit de inicio y parada antes y después de cada carácter, pero los omitiremos y solo nos preocuparemos por los 5 bits únicos para cada carácter. Los formatos de entrada y salida se analizan a continuación.

Código de Baudot

Hay dos versiones diferentes del Código Baudot: Continental y Reino Unido. Vamos a utilizar la versión del Reino Unido, que no incluye caracteres como "É" del francés nativo de Baudot. También vamos a dejar de lado todos los símbolos en la versión del Reino Unido que no se encuentran entre los caracteres ASCII imprimibles. Solo tendrá que decodificar los caracteres de la tabla a continuación, todos los cuales son caracteres ASCII imprimibles, excepto los tres caracteres de control finales que se explican debajo de la tabla.

La columna "Ltr" muestra los caracteres en modo Carta y "Fig" muestra los caracteres en modo Figura:

        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

Las últimas tres filas en la columna derecha son caracteres de control:

  • ERes Erasure . Las máquinas de telegrafía de Baudot imprimirían un símbolo similar a un asterisco para este personaje para decirle al lector que el personaje anterior debe ser ignorado, pero vamos a ser aún más amables con el lector y en realidad omitiremos (no imprimiremos) el personaje anterior . Actúa igual en los modos Carta y Figura.

  • FSes el cambio de figura . Esto cambia el conjunto de caracteres de letras a figuras. Si el decodificador ya está en modo Figura, FS se trata como un Espacio (ergo SPen la columna "Ltr"). Cuando el decodificador está en modo Figura, permanece en modo Figura hasta que se recibe un carácter LS.

  • LSes el cambio de letra . Cambia el conjunto de caracteres de figuras a letras. Si el decodificador ya está en modo Carta, LS se trata como un Espacio . Cuando está en modo Carta, el decodificador permanece en modo Carta hasta que se recibe un carácter FS.

El decodificador siempre comienza en modo Carta.

Aquí hay un ejemplo con Figure Shift, Letter Shift y Space:

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

Esto produce el mensaje MAY 15TH. Como puede ver, el primer carácter 00001(Letter Shift / Space) actúa como un espacio, porque el decodificador ya está en modo Letter. El siguiente carácter, 00010(Shift / Space) cambia el decodificador al modo Figura para imprimir 15. Luego 00001aparece de nuevo, pero esta vez actúa como cambio de letra para volver a poner el decodificador en modo carta.

Para su conveniencia, aquí están los caracteres en un formato que quizás sea más fácil de digerir en un editor, ordenados 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

La entrada será una cadena, matriz o lista de bits en el primer orden de bits menos significativo. Cada personaje estará representado por un quinteto de 5 bits. Los bits pueden estar en cualquier formato razonable, por ejemplo, una cadena binaria, una matriz de 0sys 1, una cadena de caracteres "0"y "1", un único número muy grande, etc., siempre que se asigne directamente a los bits de la transmisión.

Cada transmisión tendrá al menos un quinteto imprimible y como máximo 255 quintetos (imprimibles o no), es decir, 5–1,275 bits inclusive.

La entrada puede contener solo los bits de la transmisión, con dos excepciones permitidas: cualquier número de 0bits iniciales o finales y / o, para la entrada de cadena, se puede agregar una nueva línea final a la transmisión. Los bits o caracteres iniciales o finales no pueden agregarse antes o después de cada quinteto, es decir, no puede rellenar cada quinteto a 8 bits (o tomar cada quinteto como un solo número en una matriz, a menos que su idioma tenga un tipo entero de 5 bits) o separado quintetos con bits adicionales, por ejemplo "01111\n11100".

Notas y estuches

  1. La transmisión contendrá solo los caracteres en las columnas "Ltr" y "Fig" en la tabla de arriba. Nunca recibirá, por ejemplo, 01110en modo Figura, porque está ausente de la columna "Fig".

  2. Se supone que el decodificador siempre estará en modo Carta al comienzo de una transmisión. Sin embargo, el primer carácter puede ser un carácter FS para cambiar al modo Figura inmediatamente.

  3. Cuando el decodificador está en modo Carta, puede recibir un carácter LS, y cuando está en modo Figura puede recibir un carácter FS. En cualquier caso, se debe imprimir un carácter de espacio (ver Salida).

  4. El carácter ER nunca será el primer carácter en una transmisión, ni seguirá inmediatamente a un LS, FS u otro ER.

  5. Un carácter FS puede seguir inmediatamente a un carácter LS y viceversa.

  6. Ni el carácter LS ni el FS serán el último carácter en ninguna transmisión.

  7. Los caracteres /y -pueden recibirse en modo Carta (códigos 11000y 10001, respectivamente) o en modo Figura ( 10111 y 00111).

Salida

La salida puede estar en cualquier formato razonable, siendo el más razonable ASCII (o UTF-8, para el cual todos los caracteres representados son los mismos que ASCII). Indique en su respuesta si su salida está en otra codificación o formato.

Notas

  • El carácter de espacio (ver 3. arriba) debe ser un espacio ASCII (0x20) o el equivalente de su codificación, es decir, lo que obtiene cuando presiona la barra espaciadora.

Victorioso

Este es el . El código más corto en bytes gana.

Restricciones

  • Las lagunas estándar están prohibidas.

  • Se permiten espacios finales y / o una nueva línea final. Los espacios iniciales u otros caracteres (que no son parte de la transmisión) no están permitidos.

  • No puede usar ninguna función incorporada o de biblioteca que decodifique el Código Baudot (o cualquiera de sus descendientes, por ejemplo, Código Murray, ITA-1, etc.).

Casos de prueba

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án
fuente
1
Nota: codifiqué los casos de prueba a mano; Si ve algo que se ve mal, por favor hable.
Jordania
1
En la tabla de códigos y el resumen adjunto, el código 00010aparece SPen modo letra y FSen modo figura. De acuerdo con la descripción, si estamos en modo letra y recibimos código 00010, deberíamos cambiar al modo figura, pero los valores en la tabla parecen ser al revés. Además, viceversa para 00001.
Sok
3
Este hombre era bastante inteligente, nunca supe de la compresión utilizada en la telegrafía. Gracias por la lección de historia, hombre.
Magic Octopus Urn
44
@carusocomputing ¿verdad? Baudot no tenía educación formal más allá de la escuela primaria, pero no solo inventó el Código Baudot, sino que inventó un sistema de multiplexación que permitía a cuatro operadores usar una sola línea telegráfica simultáneamente. Encontré este panfleto de 1919 que describe sus inventos con cierto detalle súper interesante: samhallas.co.uk/repository/telegraph/b6_baudot_multiplex.pdf
Jordania

Respuestas:

6

Pyth, 98 97 95 93 90 83 80 bytes

El código contiene caracteres no imprimibles, así que aquí hay un xxdhexdump reversible :

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

Pruébalo en línea. Banco de pruebas.

Bastante largo, pero la tabla de búsqueda ocupa la mayor parte del espacio.

Para 117 bytes, esto es lo mismo sin imprimibles (aunque necesita 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

O, para 93 bytes, sin compresión en la tabla de búsqueda:

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

Toma entrada en STDIN. Como Batch no tiene conversión binaria, tengo que fingirlo usando conversión octal y hexadecimal.

  • Los primeros dos dígitos se convierten de octal (no puedo usar decimal porque el primer dígito podría ser 0). Los valores posibles son 00, 01, 10y 11. Los dos últimos tienen valor 8y 9pero quiero 2o3 menos, tomo el módulo restante 6.
  • Los últimos tres dígitos se convierten de hexadecimales. Los dígitos son 14o 252veces su valor deseado, para tomar el módulo restante 14( 252=14*18).
  • c es la cadena codificada
  • r es el resultado hasta ahora
  • d es la matriz de decodificación
  • s es el índice (teniendo en cuenta el estado de cambio) del personaje que cambia el estado de cambio
  • nes la decodificación binaria más el bit 5 de s, que es igual al estado de cambio, en cuyo caso el estado de cambio se alterna o se indexa en la matriz de decodificación para encontrar el siguiente carácter (o! para borrar)
Neil
fuente
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
fuente
2

Chip , 1069 bytes

Es algo grande, pero fue muy divertido de escribir.

Toma entrada como una cadena de "1"'sy "0"' s. (Aunque realmente solo se ve en la parte baja).

 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

Pruébalo en línea!

Nota: Erasure usa el carácter de retroceso ASCII (\x08 ), lo que significa que se verán divertidos en TIO, pero se verán bien en, digamos, xterm.

Estructura basica

En la parte superior, sobre la =línea, se encuentra el decodificador de entrada. Convierte la entrada en una de las 32 señales separadas. Estos se envían desde oarriba de= a los de abajo.

Las montañas triangulares de L'sy R' s simplemente rotan el patrón de filas separadas a columnas. La siguiente cuadrícula que traduce cada columna a su carácter de salida. Para señales desconocidas, NUL (\x00 se produce ). Para los cambios especiales, en lugar de imprimir un carácter, el pequeño blob a la derecha cambia el modo.

La cosa similar al teleférico entre las dos montañas suprime cualquier impresión entre cada quinteto, de lo contrario, esto también intentaría decodificar todos los quintetos superpuestos. Intenta reemplazarlo !con un espacio para ver esto por ti mismo. (Ejecutar en modo detallado -vtambién puede ser de interés aquí).

No estoy seguro de cómo hacer esto más pequeño en este momento; Ya es bastante denso para su tamaño.

Phlarx
fuente
0

GNU sed, 334 + 1 = 335 bytes

+1 byte para -rbandera. Toma entrada en STDIN.

Al revisar los viejos desafíos, me di cuenta de que este sería bastante fácil con sed y bueno para la práctica. No he intentado ninguna compresión, por lo que la tabla de búsqueda es más de la mitad del 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

Pruébalo en línea!

Explicación

El código funciona en dos fases: Primero, reemplaza cada ejecución de 5 dígitos binarios con los dos caracteres correspondientes (letra y figura) de una tabla de búsqueda. La tabla de búsqueda tiene el formato 𝟎𝟎𝟎𝟎𝟎𝐋𝐅𝟎𝟎𝟎𝟎𝟎𝐋𝐅 ... donde 𝟎 es un dígito binario y 𝐋 y 𝐅 son la letra y la figura correspondientes, respectivamente. %reemplaza los caracteres que faltan (este podría ser cualquier carácter que no sea nueva línea). FS/SPestá representado por f<space>y SP/LSes <space>l. ERestá representado por<< .

Luego, recorre cada par con un "cursor" correspondiente al modo actual, #para el modo letra, @para el modo figura. El #cursor elimina el segundo carácter del par y luego avanza al siguiente par, y luego @elimina el primero y avanza. En otras palabras, se #A1B8vuelve A#B8y luego AB#, y se @A1B8vuelve 1@B8y luego 18@. Cuando el #cursor se encuentra, f<space>lo elimina y se reemplaza con el @cursor, y viceversa cuando se @encuentra <space>l.

Cuando no quedan pares, el cursor final se elimina junto con los caracteres seguidos de <.

# 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án
fuente