]> www.fi.muni.cz Git - aoc2021.git/blob - 32.pl
Day 25: pretty straightforward
[aoc2021.git] / 32.pl
1 #!/usr/bin/perl -w
2
3 use v5.16;
4
5 chomp(my $data = <>);
6 # Accept also a binary string instead of hexadecimal one:
7 $data =~ s/./sprintf("%04b", hex $&)/ge if $data =~ /[2-9A-F]/;
8
9 sub chop_bits {
10         my ($bits) = @_;
11         my $rv;
12         $data =~ s/.{$bits}/$rv = eval "0b$&"; ''/e;
13         # say "chop_bits($bits) = $rv";
14         return $rv;
15 }
16
17 my $ver_sum;
18 my $result;
19
20 sub parse {
21         $ver_sum += chop_bits(3);
22         my $type = chop_bits(3);
23
24         if ($type == 4) {
25                 my $num = 0;
26                 my $more;
27                 do {
28                         $more = chop_bits(1);
29                         $num *= 16;
30                         $num += chop_bits(4);
31                 } while ($more);
32                 $result .= "$num,";
33         } else {
34                 $result .= "op$type(";
35                 if (chop_bits(1)) {
36                         my $subparts = chop_bits(11);
37                         parse() for 1 .. $subparts;
38                 } else {
39                         my $sublen = chop_bits(15);
40                         my $len = length $data;
41                         parse() while $len - length($data) < $sublen;
42                 }
43                 $result .= "),";
44         }
45 }
46
47 use List::Util qw(sum product min max);
48
49 sub op0 { sum @_; }
50 sub op1 { product @_; }
51 sub op2 { min @_; }
52 sub op3 { max @_; }
53 sub op5 { $_[0] >  $_[1] ? 1 : 0 }
54 sub op6 { $_[0] <  $_[1] ? 1 : 0 }
55 sub op7 { $_[0] == $_[1] ? 1 : 0 }
56
57 parse();
58
59 say "versions = $ver_sum";
60 say $result, ' = ', eval $result;
61