การบรรจุข้อมูลไบต์อย่างสม่ำเสมอ (COBS)


10

ฉันประหลาดใจที่นี่ยังไม่ได้โพสต์ก่อน!

โสหุ้ยไบต์บรรจุสอดคล้องอัลกอริทึม (ซัง) จะใช้ในการกำหนดเขตลำธารไบต์

เราเลือกเครื่องหมายเฟรม (เราจะใช้ 0x00) และทุก ๆ 0x00 เกิดขึ้นในสตรีมมันจะถูกแทนที่ด้วยจำนวนไบต์จนกว่าจะเกิด 0x00 ถัดไป (เราจะเรียกสิ่งนี้ว่าเป็นเหตุการณ์สำคัญ) สิ่งนี้จะช่วยลดช่วงของค่าจาก 0.255 เป็น 1.255 ทำให้ 0x00 สามารถกำหนดเฟรมในสตรีมได้อย่างไม่น่าสงสัย
ในขั้นตอนสำคัญหาก 255B ถัดไปไม่มีขนาด 0x00 สิ่งนี้จะเกินความยาวขั้นสูงสุด - อัลกอริทึมจะต้อง 'หยุด' ที่ 255B และวางอีกขั้น นี่คือ 'ค่าใช้จ่ายที่สอดคล้อง'
ไบต์แรกจะเป็นเหตุการณ์สำคัญครั้งแรกเหตุการณ์สำคัญในขั้นสุดท้ายจะเป็นจำนวนไบต์จนกว่าเครื่องหมายเฟรม

ตัวอย่างบางส่วนจาก Wikipedia (ดีที่สุดในการอ่านบทความที่มีสี):

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 ไบต์ที่ไม่เป็นศูนย์คุณไม่จำเป็นต้องเพิ่มไบต์ศูนย์ต่อท้าย วิธีนี้ช่วยประหยัดหนึ่งไบต์ในบางสถานการณ์ (อ้างถึง Wikipedia)
Arnauld

3
@LuisMendo เห็นด้วย ตอนนี้ฉันได้ดำเนินการผ่านทุกกรณีทดสอบฉันสามารถยืนยันได้ว่าขณะนี้มีการเน้นเล็กน้อย
Arnauld

@Arnauld ฉันได้ระบุชงเฟรมสุดท้ายไม่ได้อยู่แล้วจำเป็น :)
แพทริค

ในตัวอย่างไบต์แรกควรเป็น 0x03 ไม่ใช่ 0x02 ยกเว้นว่าฉันเข้าใจผิด ...
Olivier Grégoire

1
@Arnauld เกี่ยวกับกรณีพิเศษที่ลงท้ายด้วย 254 ไบต์ที่ไม่เป็นศูนย์: เห็นด้วยและนี่เป็นปัญหาแยกต่างหากกับเครื่องหมายเฟรมสุดท้าย นี่คือสาเหตุที่ตัวอย่างที่หกไม่มีการติดตาม01แต่มีสอง01s ในเก้าที่หนึ่ง (ที่มี 254 ไบต์ไม่ใช่ศูนย์ตามด้วยศูนย์)
Nick Kennedy

คำตอบ:





1

เยลลี่ , 27 ไบต์

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

ลองออนไลน์!

ลิงก์ monadic ที่ใช้อาร์เรย์ไบต์ที่ไม่ได้เข้ารหัสเป็นอินพุตและส่งคืนอาร์เรย์ไบต์ที่เข้ารหัส ตามกฎแล้วเครื่องหมายเฟรมสุดท้ายจะถูกตัดออก

คำอธิบาย

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.