]> www.fi.muni.cz Git - aoc2021.git/commitdiff
Day 16: pretty straightforward parser
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 16 Dec 2021 05:49:03 +0000 (06:49 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 16 Dec 2021 05:49:03 +0000 (06:49 +0100)
31.pl [new file with mode: 0755]
32.pl [new file with mode: 0755]

diff --git a/31.pl b/31.pl
new file mode 100755 (executable)
index 0000000..9f8f753
--- /dev/null
+++ b/31.pl
@@ -0,0 +1,60 @@
+#!/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;
+
diff --git a/32.pl b/32.pl
new file mode 100755 (executable)
index 0000000..035abc7
--- /dev/null
+++ b/32.pl
@@ -0,0 +1,82 @@
+#!/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;
+