integers_binary_encoding.sf 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/ruby
  2. # Author: Trizen
  3. # Date: 23 March 2023
  4. # https://github.com/trizen
  5. # Encode and decode a random list of integers into a binary string.
  6. func encode_integers (Array integers) {
  7. var counts = []
  8. var count = 0
  9. var bits_per_symbol = 2
  10. var processed_len = 0
  11. for k in (integers) {
  12. while (k >= bits_per_symbol) {
  13. if (count > 0) {
  14. counts << [bits_per_symbol.len(2)-1, count]
  15. processed_len += count
  16. }
  17. count = 0
  18. bits_per_symbol *= 2
  19. }
  20. ++count
  21. }
  22. counts << [[bits_per_symbol.len(2)-1, integers.len - processed_len]].grep { .tail > 0 }...
  23. var clen = counts.len
  24. var header = clen.chr
  25. for b,len in (counts) {
  26. header += chr(b)
  27. header += pack('N', len)
  28. }
  29. var bits = []
  30. for b,len in (counts) {
  31. bits << integers.splice(0, len).map{ sprintf('%0*s', b, .as_bin) }...
  32. }
  33. header + pack('B*', bits.join)
  34. }
  35. func decode_integers (String str) {
  36. var str_fh = str.open_r(:raw)
  37. var count_len = str_fh.getc.ord
  38. var counts = []
  39. count_len.times {
  40. var b = str_fh.getc.ord
  41. var l = Num(unpack('N', 4.of { str_fh.getc }.join))
  42. counts << [b, l] if (l > 0)
  43. }
  44. var chunks = []
  45. var bits_fh = str_fh.slurp.ascii2bin.open_r(:raw)
  46. for b,len in (counts) {
  47. bits_fh.read(\var chunk, len*b)
  48. chunks << chunk.slices(b)...
  49. }
  50. chunks.map { Num(_, 2) }
  51. }
  52. var integers = 1000.of { .irand }
  53. var str = encode_integers(integers.clone)
  54. say ("Encoded length: ", str.len)
  55. say ("Rawdata length: ", integers.join(' ').len)
  56. var decoded = decode_integers(str)
  57. assert_eq(integers, decoded)
  58. __END__
  59. Encoded length: 1158
  60. Rawdata length: 3621