Telegraphy Golf: Giải mã mã Baudot


31

Lý lịch

Năm 1870 Émile Baudot đã phát minh ra Baudot Code , mã hóa ký tự có độ dài cố định cho điện báo. Ông đã thiết kế mã được nhập từ bàn phím thủ công chỉ với năm phím; hai hoạt động với tay trái và ba với bên phải:

Bàn phím 5 phím Baudot

Chỉ số phải, ngón tay giữa và vòng vận hành tôi , II , và III phím, tương ứng, và chỉ số trái và ngón tay giữa hoạt động IV . (Do đó, tôi sẽ sử dụng các chữ số Tây Ả Rập của họ, tức là 1 , đến 5. ) Các ký tự được nhập dưới dạng hợp âm. Để nhập chữ "C", ví dụ, toán tử nhấn 1 , 34các phím đồng thời, trong đó một nhánh bàn chải xoay đọc từng phím theo trình tự và truyền một dòng điện hoặc, cho các phím không bị đè, không có dòng điện. Kết quả là, theo thuật ngữ hiện đại, mã hóa nhị phân đầu tiên ít nhất có ý nghĩa 5 bit, trong đó ví dụ của chúng tôi, "C", được mã hóa thành 10110.

5 bit ??

Bạn có thể nghĩ rằng 5 bit, có thể biểu thị tối đa 32 ký hiệu duy nhất, không đủ cho tất cả các chữ cái và chữ số tiếng Anh, không nói gì đến dấu câu. Baudot đã có một mánh khóe, mặc dù: Bộ ký tự của anh ta thực sự là hai bộ khác nhau: ChữHình , và anh ta đã xác định hai mã đặc biệt để chuyển đổi giữa chúng. Shift Shift , chuyển sang chế độ Chữ cái, được kích hoạt bằng cách nhấn phím 5 một mình ( 00001) và Hình Shift được kích hoạt bằng phím 4 ( 00010).

Thử thách

Thử thách của bạn là viết một chương trình hoặc chức năng giải mã truyền Baudot Code.

Việc truyền thực sự sẽ bắt đầu với một số bit khởi tạo, cộng với bit bắt đầu và dừng trước và sau mỗi ký tự, nhưng chúng ta sẽ bỏ qua chúng và chỉ lo lắng về 5 bit duy nhất cho mỗi ký tự. Định dạng đầu vào và đầu ra được thảo luận dưới đây.

Mã của Baudot

Có hai phiên bản khác nhau của Mã Baudot: Lục địa và Vương quốc Anh Chúng tôi sẽ sử dụng phiên bản Vương quốc Anh, không bao gồm các ký tự như "É" từ tiếng Pháp bản địa của Baudot. Chúng tôi cũng sẽ loại bỏ tất cả các biểu tượng trong phiên bản Vương quốc Anh không nằm trong số các ký tự ASCII có thể in được. Bạn sẽ chỉ phải giải mã các ký tự trong bảng bên dưới, tất cả đều là các ký tự ASCII có thể in được ngoại trừ ba ký tự điều khiển cuối cùng được giải thích bên dưới bảng.

Cột "Ltr" hiển thị các ký tự trong chế độ Chữ và "Hình" hiển thị các ký tự chế độ Hình:

        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

Ba hàng cuối cùng trong cột bên phải là các ký tự điều khiển:

  • ERtẩy xóa . Các máy điện báo của Baudot sẽ in biểu tượng giống dấu hoa thị cho nhân vật này để nói với người đọc rằng nhân vật trước nên được bỏ qua, nhưng chúng ta sẽ còn đẹp hơn với người đọc và thực sự bỏ qua (không in) ký tự trước . Nó hoạt động giống nhau trong cả chế độ Chữ và Hình.

  • FShình Shift . Thao tác này sẽ chuyển bộ ký tự từ Chữ sang Hình. Nếu các bộ giải mã là đã ở chế độ hình, FS được coi là một vũ trụ (ergo SPtrong cột "ltr"). Khi bộ giải mã ở chế độ Hình, nó sẽ ở chế độ Hình cho đến khi nhận được ký tự LS.

  • LSdịch chuyển thư . Nó chuyển bộ ký tự từ hình sang chữ. Nếu bộ giải mã đã ở chế độ Letter, LS được coi là Space . Khi ở chế độ Letter, bộ giải mã vẫn ở chế độ Letter cho đến khi nhận được ký tự FS.

Bộ giải mã luôn khởi động ở chế độ Letter.

Đây là một ví dụ với hình Shift, Letter Shift và Space:

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

Điều này mang lại thông điệp MAY 15TH. Như bạn có thể thấy, ký tự đầu tiên 00001(Shift Shift / Space) hoạt động như một khoảng trắng, bởi vì bộ giải mã đã ở chế độ Letter. Ký tự tiếp theo, 00010(Hình Shift / Space) chuyển bộ giải mã sang chế độ Hình để in 15. Sau đó 00001xuất hiện lại, nhưng lần này nó hoạt động như Letter Shift để đưa bộ giải mã trở lại trong chế độ Letter.

Để thuận tiện cho bạn, đây là các ký tự có định dạng có thể dễ tiêu hóa hơn trong trình chỉnh sửa, được sắp xếp theo mã:

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

Đầu vào

Đầu vào sẽ là một chuỗi, mảng hoặc danh sách các bit theo thứ tự ít quan trọng nhất đầu tiên. Mỗi ký tự sẽ được đại diện bởi một nhóm 5 bit. Các bit có thể ở bất kỳ định dạng hợp lý nào, ví dụ chuỗi nhị phân, mảng 0s và 1s, chuỗi "0""1" ký tự, một số rất lớn, v.v., miễn là nó ánh xạ trực tiếp đến các bit của truyền.

Mỗi lần truyền sẽ có ít nhất một nhóm có thể in và nhiều nhất là 255 nhóm (có thể in hoặc bằng cách khác), tức là đã bao gồm 5 bit1,275 bit.

Các đầu vào có thể chứa chỉ các bit của việc truyền tải, với hai trường hợp ngoại lệ cho phép: Bất kỳ số ở đầu hoặc cuối 0bit và / hoặc, đối với đầu vào chuỗi, một dấu xuống dòng duy nhất có thể được bổ sung vào việc truyền tải. Không thể thêm các bit hoặc ký tự đầu hoặc trước hoặc sau mỗi nhóm, nghĩa là bạn không thể đệm mỗi nhóm thành 8 bit (hoặc lấy mỗi nhóm thành một số trong một mảng, trừ khi ngôn ngữ của bạn có loại số nguyên 5 bit) hoặc riêng biệt các nhóm với bất kỳ bit bổ sung, ví dụ "01111\n11100".

Ghi chú & trường hợp cạnh

  1. Việc truyền sẽ chỉ chứa các ký tự trong cột "Ltr" và "Hình" trong bảng trên. Bạn sẽ không bao giờ nhận được ví dụ 01110trong chế độ Hình, vì nó không có trong cột "Hình".

  2. Giả định rằng bộ giải mã sẽ luôn ở chế độ Letter khi bắt đầu truyền. Tuy nhiên, ký tự đầu tiên có thể là ký tự FS để chuyển sang chế độ Hình ngay lập tức.

  3. Khi bộ giải mã ở chế độ Letter, nó có thể nhận được một ký tự LS và khi ở chế độ Hình, nó có thể nhận được một ký tự FS. Trong cả hai trường hợp, một ký tự Space phải được in (xem Đầu ra).

  4. Ký tự ER sẽ không bao giờ là ký tự đầu tiên trong truyền, cũng không bao giờ ngay lập tức đi theo LS, FS hoặc ER khác.

  5. Một nhân vật FS có thể ngay lập tức đi theo một nhân vật LS và ngược lại.

  6. Cả nhân vật LS và FS sẽ không phải là nhân vật cuối cùng trong bất kỳ việc truyền tải nào.

  7. Các ký tự /-ký tự có thể được nhận ở chế độ Chữ (mã 1100010001, tương ứng) hoặc chế độ Hình ( 1011100111).

Đầu ra

Đầu ra có thể ở bất kỳ định dạng hợp lý nào, hợp lý nhất là ASCII (hoặc UTF-8, với tất cả các ký tự được biểu diễn giống như ASCII). Vui lòng cho biết trong câu trả lời của bạn nếu đầu ra của bạn ở dạng mã hóa hoặc định dạng khác.

Ghi chú

  • Ký tự khoảng trắng (xem 3. ở trên) phải là khoảng trắng ASCII (0x20) hoặc tương đương mã hóa của bạn, tức là những gì bạn nhận được khi nhấn thanh dấu cách.

Chiến thắng

Đây là . Mã ngắn nhất tính bằng byte thắng.

Hạn chế

  • Sơ hở tiêu chuẩn bị cấm.

  • Không gian lưu trữ và / hoặc một dòng mới duy nhất được cho phép. Không gian hàng đầu hoặc các ký tự khác (không phải là một phần của truyền) không được phép.

  • Bạn không được sử dụng bất kỳ chức năng thư viện hoặc chức năng tích hợp nào để giải mã Mã Baudot (hoặc bất kỳ hậu duệ nào của nó, ví dụ: Mã Murray, ITA-1, v.v.).

Các trường hợp thử nghiệm

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
Lưu ý: Tôi đã mã hóa các trường hợp kiểm tra bằng tay; nếu bạn thấy bất cứ điều gì có vẻ sai xin vui lòng lên tiếng.
Jordan

1
Trong bảng mã và thông báo đi kèm, mã 00010được liệt kê SPở chế độ chữ và FSở chế độ hình. Theo mô tả, nếu chúng ta ở chế độ chữ cái và chúng ta nhận được mã 00010, chúng ta nên chuyển sang chế độ hình, nhưng các giá trị trong bảng dường như ngược lại. Ngoài ra, ngược lại cho 00001.
Sok

3
Người đàn ông này khá thông minh, tôi chưa bao giờ biết về nén được sử dụng trong điện báo. Cảm ơn vì bài học lịch sử.
Bạch tuộc ma thuật Urn

4
@carusocomputing Phải không ?? Baudot không có giáo dục chính thức ngoài trường tiểu học, nhưng ông không chỉ phát minh ra Baudot Code, ông còn phát minh ra một hệ thống ghép kênh cho phép bốn nhà khai thác sử dụng đồng thời một đường dây điện báo. Tôi tìm thấy cuốn sách nhỏ năm 1919 này mô tả các phát minh của anh ấy trong một số chi tiết siêu thú vị: samhallas.co.uk/reposeective/telegraph/b6_baudot_multiplex.pdf
Jordan

Câu trả lời:


6

Pyth, 98 97 95 93 90 83 80 byte

Mã này chứa các ký tự không thể in được, vì vậy đây là một xxdhexdump có thể đảo ngược :

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

Hãy thử trực tuyến. Bộ thử nghiệm.

Khá dài, nhưng bảng tra cứu chiếm gần một nửa không gian.

Đối với 117 byte, đây là điều tương tự mà không thể in được (mặc dù cần 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

Hoặc, đối với 93 byte, không nén trên bảng tra cứu:

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 byte

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

Hàng loạt, 306 304 byte

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

Đưa đầu vào vào STDIN. Vì Batch không có chuyển đổi nhị phân, tôi phải giả mạo nó bằng cách sử dụng chuyển đổi bát phân và hex.

  • Hai chữ số đầu tiên được chuyển đổi từ bát phân (Tôi không thể sử dụng số thập phân vì chữ số đầu tiên có thể là 0). Giá trị có thể là 00, 01, 1011. Hai cái sau có giá trị 89nhưng tôi muốn 2hoặc 3vì vậy tôi lấy modulo còn lại 6.
  • Ba chữ số cuối cùng được chuyển đổi từ thập lục phân. Chữ số là một trong hai 14hoặc 252lần giá trị của họ mong muốn, để tôi lấy modulo còn lại 14( 252=14*18).
  • c là chuỗi mã hóa
  • r là kết quả cho đến nay
  • d là mảng giải mã
  • s là chỉ số (đưa trạng thái dịch chuyển vào tài khoản) của ký tự chuyển trạng thái dịch chuyển
  • nlà giải mã nhị phân cộng với bit 5 s, bằng với trạng thái dịch chuyển, trong trường hợp đó trạng thái dịch chuyển được bật hoặc lập chỉ mục vào mảng giải mã để tìm ký tự tiếp theo (hoặc! để xóa)

3

PHP, 206 byte

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

Chip , 1069 byte

Đó là một big'n, nhưng khá thú vị để viết.

Lấy đầu vào dưới dạng một chuỗi "1"'s và "0"'. (Mặc dù nó thực sự chỉ nhìn vào bit thấp.)

 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

Hãy thử trực tuyến!

Lưu ý: Erasure sử dụng ký tự backspace ASCII ( \x08), có nghĩa là chúng sẽ trông buồn cười trong TIO, nhưng chúng trông ổn trong, giả sử, xterm.

Cấu trúc cơ bản

Ở trên cùng, phía trên =dòng, là bộ giải mã đầu vào. Nó biến đầu vào thành một trong 32 tín hiệu riêng biệt. Chúng được gửi từ obên trên =đến những người bên dưới.

Các dãy núi hình tam giác của LRchỉ xoay mô hình từ các hàng riêng biệt sang các cột. Lưới bên dưới chuyển từng cột thành ký tự đầu ra của nó. Đối với các tín hiệu không xác định, NUL ( \x00) được tạo ra. Đối với các ca đặc biệt, thay vì in một ký tự, đốm màu bên phải sẽ thay đổi chế độ.

Cáp treo giống như vật giữa hai ngọn núi sẽ ngăn chặn mọi sự in ấn giữa mỗi nhóm, nếu không, điều này cũng sẽ cố gắng giải mã tất cả các nhóm bị chồng chéo. Hãy thử thay thế !bằng một không gian để thấy điều này cho chính mình. (Chạy ở chế độ dài dòng -vcũng có thể được quan tâm ở đây.)

Tôi không chắc chắn làm thế nào để làm cho nó nhỏ hơn vào lúc này; kích thước của nó khá dày đặc.


0

GNU sed, 334 + 1 = 335 byte

+1 byte cho -rcờ. Đưa đầu vào vào STDIN.

Nhìn qua những thử thách cũ tôi nhận ra rằng thử thách này sẽ khá dễ dàng với sed và tốt cho việc luyện tập. Tôi chưa thử nén, vì vậy bảng tra cứu có hơn một nửa mã.

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

Hãy thử trực tuyến!

Giải trình

Mã này hoạt động theo hai giai đoạn: Đầu tiên, nó thay thế mỗi lần chạy 5 chữ số nhị phân bằng hai ký tự (chữ và hình) tương ứng từ một bảng tra cứu. Bảng tra cứu có định dạng 𝟎𝟎𝟎𝟎𝟎𝐋𝐅𝟎𝟎𝟎𝟎𝟎𝐋𝐅, trong đó là một chữ số nhị phân và 𝐋 và lần lượt là chữ và hình tương ứng. %là viết tắt của các ký tự bị thiếu (đây có thể là bất kỳ ký tự nào ngoài dòng mới). FS/SPđược đại diện bởi f<space>SP/LS<space>l. ERđược đại diện bởi <<.

Sau đó, nó bước qua từng cặp với một "con trỏ" tương ứng với #chế độ hiện tại, đối với chế độ chữ cái, @đối với chế độ hình. Con #trỏ loại bỏ ký tự thứ hai của cặp và sau đó chuyển sang cặp tiếp theo và @loại bỏ ký tự đầu tiên và tiến lên. Nói cách khác, #A1B8trở thành A#B8và sau đó AB#, và @A1B8trở thành 1@B8và sau đó 18@. Khi #con trỏ gặp f<space>nó sẽ xóa nó và thay thế nó bằng @con trỏ và ngược lại khi @gặp <space>l.

Khi không còn cặp nào, con trỏ cuối cùng sẽ bị xóa cùng với bất kỳ ký tự nào theo sau <.

# 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.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.