Nhồi nhét Byte liên tục (COBS)


10

Tôi ngạc nhiên điều này đã không được đăng trước đó!

Thuật toán nhất quán Overte Byte Stuffing (COBS) được sử dụng để phân định các luồng byte.

Chúng tôi chọn điểm đánh dấu khung (chúng tôi sẽ sử dụng 0x00) và bất cứ nơi nào 0x00 xảy ra trong luồng, nó sẽ được thay thế bằng số byte cho đến khi 0x00 tiếp theo xảy ra (chúng tôi sẽ gọi đây là cột mốc). Điều này làm giảm phạm vi của các giá trị từ 0..255 xuống 1..255, cho phép 0x00 phân định rõ ràng các khung trong luồng.
Tại một cột mốc, nếu 255B tiếp theo không chứa 0x00 thì điều này vượt quá độ dài cột mốc tối đa - thuật toán phải 'dừng lại' ở 255B và đặt một cột mốc khác. Đây là "chi phí nhất quán".
Byte đầu tiên sẽ là cột mốc đầu tiên, cột mốc cuối cùng sẽ là số byte cho đến khi đánh dấu khung.

Một số ví dụ từ Wikipedia (tốt nhất để đọc bài viết có màu):

0x00 as frame marker

Unencoded data (hex)    Encoded with COBS (hex)
00                      01 01 00
00 00                   01 01 01 00
11 22 00 33             03 11 22 02 33 00
11 22 33 44             05 11 22 33 44 00
11 00 00 00             02 11 01 01 01 00
01 02 03 ... FD FE      FF 01 02 03 ... FD FE 00
00 01 02 ... FC FD FE   01 FF 01 02 ... FC FD FE 00
01 02 03 ... FD FE FF   FF 01 02 03 ... FD FE 02 FF 00
02 03 04 ... FE FF 00   FF 02 03 04 ... FE FF 01 01 00
03 04 05 ... FF 00 01   FE 03 04 05 ... FF 02 01 00

Thách thức: để thực hiện điều này trong chương trình ngắn nhất.

  • Đầu vào là một luồng / mảng byte chưa được mã hóa, đầu ra là một luồng / mảng byte được mã hóa
  • Sử dụng bất kỳ loại đầu vào / đầu ra tiêu chuẩn nhị phân
  • Điểm đánh dấu khung cuối cùng là không cần thiết
  • Chương trình có thể trả về một mảng quá khổ
  • Luồng kết thúc với 254 byte khác không không yêu cầu 0x00 trailing

Ghi chú

  • Thời gian hoàn trả trong trường hợp xấu nhất là numBytes + (numBytes / 254) + 1

Thí dụ

Chúng ta có mảng byte

[0] 0x01
[1] 0x02
[2] 0x00
[3] 0x03
[4] 0x04
[5] 0x05
[6] 0x00
[7] 0x06

Đối với mỗi 0x00chúng ta cần nêu (trong một cột mốc), nơi tiếp theo 0x00sẽ có.

[0] 0x03   #Milestone. Refers to the original [2] - "The next 0x00 is in 3B"
[1] 0x01   #Original [0]
[2] 0x02   #Original [1]
[3] 0x04   #Milestone. Refers to the original [6] - "The next 0x00 is in 4B"
[4] 0x03   #
[5] 0x04   #
[6] 0x05   # Originals [3..5]
[7] 0x02   #Milestone. Refers to the end frame marker
[8] 0x06   #Original [7]
[9] 0x00   #Optional. End frame marker.

3
Có lẽ bạn nên bao gồm điều này trong thông số kỹ thuật: Như một ngoại lệ đặc biệt, nếu một gói kết thúc bằng một nhóm gồm 254 byte khác không, thì không cần thiết phải thêm byte 0 ở cuối. Điều này tiết kiệm một byte trong một số tình huống. (trích dẫn Wikipedia)
Arnauld

3
@LuisMendo Đồng ý. Bây giờ tôi đã duyệt qua tất cả các trường hợp thử nghiệm, tôi có thể xác nhận rằng điều này hiện chưa được xác định rõ.
Arnauld

@Arnauld, tôi đã tuyên bố rằng trình tạo khung kết thúc không cần thiết nữa :)
Patrick

Trong ví dụ, byte đầu ra đầu tiên phải là 0x03, không phải 0x02, trừ khi tôi nhầm ...
Olivier Grégoire

1
@Arnauld liên quan đến trường hợp đặc biệt kết thúc với 254 byte khác không: đồng ý và đây là vấn đề riêng đối với điểm đánh dấu khung cuối cùng. Đó là lý do tại sao ví dụ thứ sáu không có dấu ở cuối 01nhưng có hai 01s trong số thứ chín (trong đó có 254 byte khác không theo sau là 0).
Nick Kennedy

Câu trả lời:





1

Thạch , 27 byte

Oµ=0ks€254Ẏḟ€0L‘;Ɗ€F;Ṫ¬x`ƊỌ

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

Một liên kết đơn âm lấy một mảng byte không được mã hóa làm đầu vào và trả về mảng byte được mã hóa. Theo quy tắc, điểm đánh dấu khung cuối cùng được bỏ qua.

Giải trình

Oµ                          | Convert to integer and start a new monadic chain
  =0k                       | Split after zeros
     s€254                  | Split each list into length 254 lists
          Ẏ                 | Tighten (reduce list depth by 1)
           ḟ€0              | Filter zeros out from each list
              L‘;Ɗ€         | Prepend the list length plus one to each list
                   F        | Flatten
                    ;Ṫ¬x`Ɗ  | Append an additional 1 if the original list ended with zero
                          Ọ | Convert back to bytes


0

J , 103 ký tự

Lưu ý kết quả từ trường hợp thử nghiệm cuối cùng khác với wiki và các ngôn ngữ khác. Điều này là do con trỏ này đến byte 0,6 ở ranh giới. Mọi thứ trở nên dễ dàng hơn rất nhiều, nếu điều này không được coi là trường hợp đặc biệt.

f =: 3 : 0
  k =. I. (y,0)=0
  s =. - 2 (-/) \ k
  (>: y i. 0), s (}:k) } y
 )

 f2 =: 3 : 0
   f each _254 <\ y
 )

Dùng thử trực tuyến


Bạn có thể giảm xuống 1 byte bằng cách xóa khoảng trống ở cuối dòng cuối cùng.
ngerak
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.