Последовательное заполнение байтов (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 ненулевых байтов, нет необходимости добавлять завершающий нулевой байт. Это сохраняет один байт в некоторых ситуациях. (цитирует Википедию)
Арно
3
@LuisMendo Согласен. Теперь, когда я прошел все тестовые случаи, я могу подтвердить, что это немного занижено.
Арно
@Arnauld, я уже говорил, что в конечном итоге производитель кадров не нужен :)
Патрик,
В этом примере первый выходной байт должен быть 0x03, а не 0x02, если я не ошибаюсь ...
Оливье Грегуар,
1
@Arnauld относительно особого случая окончания с 254 ненулевыми байтами: согласен, и это отдельная проблема для окончательного маркера кадра. Вот почему в шестом примере нет трейлинга, 01а 01в девятом два s (где 254 ненулевых байта, за которыми следует ноль).
Ник Кеннеди

Ответы:

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 знака

Обратите внимание, что результат последнего теста отличается от вики и других языков. Это связано с указателем на 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