]> www.fi.muni.cz Git - aoc.git/commitdiff
32.pl: cleanup
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 16 Dec 2021 08:32:12 +0000 (09:32 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 16 Dec 2021 08:41:46 +0000 (09:41 +0100)
32.pl

diff --git a/32.pl b/32.pl
index 035abc70e0ab5fa1c2121efb3e0a635556072b24..390c25dee7b0fbe6585fb3e691ed9773d4e0605d 100755 (executable)
--- a/32.pl
+++ b/32.pl
@@ -2,81 +2,60 @@
 
 use v5.16;
 
-chomp(my $packet = <>);
-$packet =~ s/./sprintf("%04b", hex $&)/ge if $packet =~ /[2-9A-F]/;
+chomp(my $data = <>);
+# Accept also a binary string instead of hexadecimal one:
+$data =~ s/./sprintf("%04b", hex $&)/ge if $data =~ /[2-9A-F]/;
 
-sub get_b (\$$) {
-       my ($ppack, $bits) = @_;
+sub chop_bits {
+       my ($bits) = @_;
        my $rv;
-       $$ppack =~ s/.{$bits}/$rv=eval"0b$&";''/e;
-       # say "get_b $bits=$rv";
+       $data =~ s/.{$bits}/$rv = eval "0b$&"; ''/e;
+       # say "chop_bits($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);
+sub parse {
+       $ver_sum += chop_bits(3);
+       my $type = chop_bits(3);
 
-       if ($typ == 4) {
+       if ($type == 4) {
                my $num = 0;
-               while (get_b($pp, 1)) {
+               my $more;
+               do {
+                       $more = chop_bits(1);
                        $num *= 16;
-                       $num += get_b($pp, 4);
-               }
-               $num *= 16;
-               $num += get_b($pp, 4);
+                       $num += chop_bits(4);
+               } while ($more);
                $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}//;
-                       }
+               $result .= "op$type(";
+               if (chop_bits(1)) {
+                       my $subparts = chop_bits(11);
+                       parse() for 1 .. $subparts;
                } 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;
-                       }
+                       my $sublen = chop_bits(15);
+                       my $len = length $data;
+                       parse() while $len - length($data) < $sublen;
                }
                $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;
-       } 
-}
+sub op0 { sum @_; }
+sub op1 { product @_; }
+sub op2 { min @_; }
+sub op3 { max @_; }
+sub op5 { $_[0] >  $_[1] ? 1 : 0 }
+sub op6 { $_[0] <  $_[1] ? 1 : 0 }
+sub op7 { $_[0] == $_[1] ? 1 : 0 }
+
+parse();
 
-parse($packet);
+say "versions = $ver_sum";
 say $result, ' = ', eval $result;