--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.16;
+
+chomp(my $packet = <>);
+$packet =~ s/./sprintf("%04b", hex $&)/ge if $packet =~ /[2-9A-F]/;
+
+sub get_b (\$$) {
+ my ($ppack, $bits) = @_;
+ my $rv;
+ $$ppack =~ s/.{$bits}/$rv=eval"0b$&";''/e;
+ return $rv;
+}
+
+my $ver_sum;
+my $result;
+sub parse {
+ my $pp = shift;
+
+ my $l = length $pp;
+ my $ver = get_b($pp, 3);
+ $ver_sum += $ver;
+ my $typ = get_b($pp, 3);
+ if ($typ == 4) {
+ my $num = 0;
+ while (get_b($pp, 1)) {
+ $num *= 16;
+ $num += get_b($pp, 4);
+ }
+ $num *= 16;
+ $num += get_b($pp, 4);
+ $result .= "$num,";
+ } else {
+ $result .= "op($typ,";
+ my $li = get_b($pp, 1);
+ if ($li) {
+ my $subp = get_b($pp, 11);
+ for (1 .. $subp) {
+ my $l1 = parse($pp);
+ $pp =~ s/.{$l1}//;
+ }
+ } else {
+ my $subl = get_b($pp, 15);
+ my $s = substr($pp, 0, $subl);
+ $pp =~ s/.{$subl}//;
+ while ($subl) {
+ my $l1 = parse($s);
+ $s =~ s/.{$l1}//;
+ $subl -= $l1;
+ }
+ }
+ $result .= ")";
+ }
+ return $l - length($pp);
+}
+
+parse($packet);
+say $result;
+say $ver_sum;
+
--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.16;
+
+chomp(my $packet = <>);
+$packet =~ s/./sprintf("%04b", hex $&)/ge if $packet =~ /[2-9A-F]/;
+
+sub get_b (\$$) {
+ my ($ppack, $bits) = @_;
+ my $rv;
+ $$ppack =~ s/.{$bits}/$rv=eval"0b$&";''/e;
+ # say "get_b $bits=$rv";
+ return $rv;
+}
+
+my $ver_sum;
+my $result;
+sub parse {
+ my $pp = shift;
+
+ my $l = length $pp;
+ my $ver = get_b($pp, 3);
+ $ver_sum += $ver;
+ my $typ = get_b($pp, 3);
+
+ if ($typ == 4) {
+ my $num = 0;
+ while (get_b($pp, 1)) {
+ $num *= 16;
+ $num += get_b($pp, 4);
+ }
+ $num *= 16;
+ $num += get_b($pp, 4);
+ $result .= "$num,";
+ } else {
+ $result .= "op($typ,";
+ my $li = get_b($pp, 1);
+ if ($li) {
+ my $subp = get_b($pp, 11);
+ for (1 .. $subp) {
+ my $l1 = parse($pp);
+ $pp =~ s/.{$l1}//;
+ }
+ } else {
+ my $subl = get_b($pp, 15);
+ my $s = substr($pp, 0, $subl);
+ $pp =~ s/.{$subl}//;
+ while ($subl) {
+ my $l1 = parse($s);
+ $s =~ s/.{$l1}//;
+ $subl -= $l1;
+ }
+ }
+ $result .= "),";
+ }
+ return $l - length($pp);
+}
+
+use List::Util qw(sum product min max);
+
+sub op {
+ my ($id, @rest) = @_;
+ if ($id == 0) {
+ return sum @rest;
+ } elsif ($id == 1) {
+ return product @rest;
+ } elsif ($id == 2) {
+ return min @rest;
+ } elsif ($id == 3) {
+ return max @rest;
+ } elsif ($id == 5) {
+ return $rest[0] > $rest[1] ? 1 : 0;
+ } elsif ($id == 6) {
+ return $rest[0] < $rest[1] ? 1 : 0;
+ } elsif ($id == 7) {
+ return $rest[0] == $rest[1] ? 1 : 0;
+ }
+}
+
+parse($packet);
+say $result, ' = ', eval $result;
+