一貫したオーバーヘッドバイトスタッフィング(COBS)


10

これが以前に投稿されていないことに驚いています!

一貫オーバーヘッド・バイトスタッフィング(COBS)アルゴリズムが区切バイトストリームに使用されます。

フレームマーカー(0x00を使用します)を選択し、ストリーム内で0x00が発生するたびに、次の0x00が発生するまでバイト数で置き換えます(これをマイルストーンと呼びます)。これにより、値の範囲が0..255から1..255に減少し、0x00がストリーム内のフレームを明確に区切ることができるようになります。
マイルストーンで、次の255Bに0x00が含まれていない場合、これは最大マイルストーン長を超えます-アルゴリズムは255Bで「停止」し、別のマイルストーンを配置する必要があります。これは「一貫したオーバーヘッド」です。
最初のバイトは最初のマイルストーンになり、最後のマイルストーンはフレームマーカーまでのバイト数になります。

ウィキペディアのいくつかの例(色分けされている記事を読むのに最適です):

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

課題:最短のプログラムでこれを実装する。

  • 入力はエンコードされていないバイトストリーム/配列、出力はエンコードされたバイトストリーム/配列です
  • あらゆる種類のバイナリ標準入出力を使用する
  • 最終フレームマーカーは必要ありません
  • プログラムは特大の配列を返すことができます
  • ゼロ以外の254バイトで終了するストリームは、末尾の0x00を必要としません

ノート

  • 最悪の場合の戻り長は numBytes + (numBytes / 254) + 1

バイト配列があります

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

それぞれ0x00について、次0x00がどこにあったかを(マイルストーンで)述べる必要があります。

[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
おそらくこれを仕様に含める必要があります。特別な例外として、パケットがゼロ以外の254バイトのグループで終了する場合、後続のゼロバイトを追加する必要はありません。これにより、状況によっては1バイトが節約されます。(ウィキペディアの引用)
アーノールド

3
@LuisMendo同意する。これですべてのテストケースについて説明したので、これは現在少し仕様が不十分であることを確認できます。
アーノールド

@アーナウルド、とにかくエンドフレームメーカーは必要ないと述べた:)
Patrick

例では、第一の出力バイトは、0x03のではなく、0x02のでなければなりません私は誤解だ場合を除き...
オリヴィエ・グレゴワール

1
ゼロ以外の254バイトで終了する特殊なケースに関する@Arnauld:同意します。これは、最終的なフレームマーカーとは別の問題です。そのため、6番目の例には末尾01がありませんが01、9 番目の例には2つのがあります(ゼロ以外のバイトが254あり、その後にゼロが続く)。
Nick Kennedy

回答:





1

ゼリー、27バイト

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

オンラインでお試しください!

エンコードされていないバイト配列を入力として受け取り、エンコードされたバイト配列を返すモナディックリンク。ルールにより、最終フレームマーカーは省略されます。

説明

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文字

最後のテストケースの結果がwikiや他の言語と異なることに注意してください。これは、境界の254番目のゼロバイトへのこのポインタが原因です。これを特別なケースとして扱わなければ、物事はずっと簡単になります。

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

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

オンラインで試す


最後の行の末尾にある末尾のスペースを削除することで、1バイト減らすことができます。
ouflak
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.