Телеграфічний гольф: Розшифруйте Код Бодо


31

Фон

У 1870 році Еміль Бодо винайшов Код Бодо , кодування символів фіксованої довжини для телеграфії. Він сконструював код, який потрібно вводити з ручної клавіатури лише з п'ятьма клавішами; двоє оперовані лівою рукою і три правою:

5-клавішна програма Бодо

Правий вказівний, середній та безіменний пальці керують клавішами I , II та III відповідно, а лівий вказівний та середній пальці працюють IV та . (Відтепер я буду використовувати їх західноарабські цифри, тобто від 1 до 5. ) Символи вводяться як акорди. Наприклад, для введення літери "C", наприклад, оператор натискає значення 1 , 3 і 4клавіші одночасно, після чого обертається ручка кисті читає кожну клавішу послідовно і передає струм або, якщо клавіші не натиснуті, немає струму. Результатом цього є сучасне 5-бітове найменш значуще-бітове перше бінарне кодування, в якому наш приклад "C" кодується як 10110.

5 біт ??

Ви можете подумати, що 5 біт, які можуть виразити не більше 32 унікальних символів, недостатньо навіть для всіх англійських букв та цифр, щоб не сказати нічого пунктуаційного. Однак Бодо мав хитрість до рукава: Його набір персонажів насправді є двома різними наборами: Letters and Figures , і він визначив два спеціальні коди для перемикання між ними. Зміна букви , яка переходить у режим Букви, активується одним натисканням клавіші 5 ( 00001), а Фігура Зсув активовано клавішею 4 ( 00010).

Виклик

Ваше завдання полягає в тому, щоб написати програму чи функцію, яка розшифровує передачу коду Бодо.

Справжня передача розпочнеться з декількох бітів ініціалізації, плюс запуск та стоп біт до та після кожного символу, але ми збираємось пропустити їх і турбуємось лише про 5 унікальних бітів для кожного символу. Формати введення та виведення обговорюються нижче.

Код Бодо

Є дві різні версії коду Бодо: Континентальний та Великобританія. Ми будемо використовувати версію Великобританії, яка не містить символів типу "É" з рідної французької мови Бодо. Ми також не будемо залишати всі символи у Великобританії, які не належать до друку 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.

  • FS- Зміна фігури . Це перемикає набір символів з літер на цифри. Якщо декодер вже знаходиться в режимі малюнка, FS трактується як пробіл (ergo SPу стовпці "Ltr"). Коли декодер перебуває у режимі малюнка, він залишається у режимі малюнка, доки не буде отримано символ LS.

  • LS- Зміна літер . Він перемикає набір символів з цифр на літери. Якщо декодер вже в режимі Letter, LS трактується як пробіл . У режимі Letter декодер залишається в режимі Letter до отримання символу FS.

Декодер завжди запускається в режимі Letter.

Ось приклад з "Зміна фігури", "Зміна літери" та пробіл:

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(Letter Shift / Space) символ виступає як пробіл, оскільки декодер вже в режимі Letter. Наступний символ 00010((Зміна фігури / пробіл) перемикає декодер на режим малюнка для друку 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у режимі "Фігура", оскільки він відсутній у стовпці "Fig".

  2. Передбачається, що декодер завжди буде в режимі Letter на початку передачі. Однак перший символ може бути символом FS, щоб негайно перейти в режим малюнка.

  3. Коли декодер перебуває в режимі Letter, він може приймати символ LS, а коли він перебуває у режимі Рисунок, він може приймати символ FS. У будь-якому випадку повинен бути надрукований символ пробілу (див. Вихідний результат).

  4. Символ ER ніколи не буде першим символом в передачі, і він не буде негайно слідувати за LS, FS або іншим ER.

  5. Символ FS може негайно слідувати за символом LS і навпаки.

  6. Ні символ LS, ні FS не будуть останнім символом у будь-якій передачі.

  7. /І -символи можуть бути отримані в будь-якому режимі Letter (кодів 11000і 10001, відповідно) або в режимі (рис 10111 і 00111).

Вихідні дані

Вихід може бути у будь-якому розумному форматі, найбільш розумним є ASCII (або UTF-8, для якого всі представлені символи такі ж, як ASCII). Будь ласка, вкажіть у своїй відповіді, чи є ваш вихід у іншому кодуванні чи форматі.

Примітки

  • Символ пробілу (див. Вище 3) повинен бути простором ASCII (0x20) або еквівалентом кодування, тобто тим, що ви отримуєте, натискаючи пробіл.

Перемога

Це . Виграє найкоротший код у байтах.

Обмеження

  • Стандартні лазівки заборонені.

  • Дозволені пробіли та / або один останній новий рядок. Провідні пробіли або інші символи (які не є частиною передачі) заборонені.

  • Ви не можете використовувати будь-які вбудовані або бібліотечні функції, які декодують Код Бодо (або будь-якого з його нащадків, наприклад, Код Мюррея, 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вказаний як SPв буквеному режимі, так і FSу цифровому режимі. Згідно з описом, якщо ми перебуваємо в літерному режимі і отримуємо код 00010, нам слід перейти до режиму цифр, але значення в таблиці, здається, навпаки. Також навпаки для 00001.
Сік

3
Цей чоловік був досить чортово розумний, я ніколи не знав про стиснення, яке використовується в телеграфії. Дякую за урок історії.
Чарівна урва восьминога

4
@carusocomputing Right ?? У Бодо не було формальної освіти поза початковою школою, але він не тільки винайшов Код Бодо, він винайшов систему мультиплексування, яка дозволила чотирьом операторам одночасно використовувати одну телеграфну лінію. Я знайшов цей памфлет 1919 року, який детально описує його винаходи: супер цікаво: samhallas.co.uk/repository/telegraph/b6_baudot_multiplex.pdf
Йорданія,

Відповіді:


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

Пакетна, 306 304 байт

@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). Можливі значення 00, 01, 10і 11. Останні два мають значення 8і , 9але я хочу , 2або 3так я взяти залишок по модулю 6.
  • Останні три цифри перетворюються з шістнадцяткової. Цифри є 14або 252кратними їх бажаного значення, я вважаю модуль, що залишився 14( 252=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 байт

Це big'n, але писати було досить весело.

Приймає введення як рядок "1"'s і "0"' s. (Хоча це насправді дивиться лише на низький шматочок.)

 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 backspace ( \x08), це означає, що вони будуть виглядати смішно в TIO, але вони добре виглядають, скажімо, у xterm.

Основна структура

Вгорі, над =лінією, знаходиться вхідний декодер. Він перетворює вхід в один з 32 окремих сигналів. Вони надсилаються від o"вище" =до "нижче".

Трикутні гори L's і 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/SPпредставлений f<space>і SP/LSє <space>l. ERпредставлена <<.

Потім він переходить через кожну пару з "курсором", відповідним поточному #режиму - для літерного режиму, @для режиму фігури. #Курсор видаляє другий символ з пари , а потім переходить до наступній парі, і @видаляє перший і досягнення. Іншими словами, #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.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.