-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathelias_gamma_encoding.pl
70 lines (47 loc) · 1.41 KB
/
elias_gamma_encoding.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/perl
# Author: Trizen
# Date: 13 June 2023
# https://github.com/trizen
# Implementation of the Elias gamma encoding scheme.
# Reference:
# COMP526 7-5 SS7.4 Run length encoding
# https://youtube.com/watch?v=3jKLjmV1bL8
use 5.036;
sub read_bit ($fh, $bitstring) {
if (($$bitstring // '') eq '') {
$$bitstring = unpack('b*', getc($fh) // return undef);
}
chop($$bitstring);
}
sub elias_encoding ($integers) {
my $bitstring = '';
foreach my $k (scalar(@$integers), @$integers) {
my $t = sprintf('%b', $k + 1);
$bitstring .= ('1' x (length($t) - 1)) . '0' . substr($t, 1);
}
pack('B*', $bitstring);
}
sub elias_decoding ($str) {
open my $fh, '<:raw', \$str;
my @ints;
my $len = 0;
my $buffer = '';
for (my $k = 0 ; $k <= $len ; ++$k) {
my $bl = 0;
++$bl while (read_bit($fh, \$buffer) eq '1');
push @ints, oct('0b' . '1' . join('', map { read_bit($fh, \$buffer) } 1 .. $bl)) - 1;
if ($k == 0) {
$len = pop(@ints);
}
}
return \@ints;
}
my @integers = map { int(rand($_)) } 1 .. 1000;
my $str = elias_encoding([@integers]);
say "Encoded length: ", length($str);
say "Rawdata length: ", length(join(' ', @integers));
my $decoded = elias_decoding($str);
join(' ', @integers) eq join(' ', @$decoded) or die "Decoding error";
__END__
Encoded length: 1777
Rawdata length: 3594