12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- #!/usr/bin/ruby
- # Author: Trizen
- # Date: 23 March 2023
- # https://github.com/trizen
- # Encode and decode a random list of integers into a binary string.
- func encode_integers (Array integers) {
- var counts = []
- var count = 0
- var bits_per_symbol = 2
- var processed_len = 0
- for k in (integers) {
- while (k >= bits_per_symbol) {
- if (count > 0) {
- counts << [bits_per_symbol.len(2)-1, count]
- processed_len += count
- }
- count = 0
- bits_per_symbol *= 2
- }
- ++count
- }
- counts << [[bits_per_symbol.len(2)-1, integers.len - processed_len]].grep { .tail > 0 }...
- var clen = counts.len
- var header = clen.chr
- for b,len in (counts) {
- header += chr(b)
- header += pack('N', len)
- }
- var bits = []
- for b,len in (counts) {
- bits << integers.splice(0, len).map{ sprintf('%0*s', b, .as_bin) }...
- }
- header + pack('B*', bits.join)
- }
- func decode_integers (String str) {
- var str_fh = str.open_r(:raw)
- var count_len = str_fh.getc.ord
- var counts = []
- count_len.times {
- var b = str_fh.getc.ord
- var l = Num(unpack('N', 4.of { str_fh.getc }.join))
- counts << [b, l] if (l > 0)
- }
- var chunks = []
- var bits_fh = str_fh.slurp.ascii2bin.open_r(:raw)
- for b,len in (counts) {
- bits_fh.read(\var chunk, len*b)
- chunks << chunk.slices(b)...
- }
- chunks.map { Num(_, 2) }
- }
- var integers = 1000.of { .irand }
- var str = encode_integers(integers.clone)
- say ("Encoded length: ", str.len)
- say ("Rawdata length: ", integers.join(' ').len)
- var decoded = decode_integers(str)
- assert_eq(integers, decoded)
- __END__
- Encoded length: 1158
- Rawdata length: 3621
|