]> www.fi.muni.cz Git - aoc.git/blob - 2023/37.pl
Day 19: not bad, but too slow to write
[aoc.git] / 2023 / 37.pl
1 #!/usr/bin/perl -w
2
3 use v5.38;
4 use experimental 'for_list';
5 use List::Util qw(sum);
6
7 my %wfl;
8 while (<>) {
9         chomp;
10         last if !length;
11         my ($name, $rest) = /(\w+)\{(\S+)\}/;
12         my @rules;
13         for my $r (split /,/, $rest) {
14                 my ($id, $op, $val, $rule) = $r =~ /(\w+)(?:(\W)(\d+):(\w+))?/;
15                 push @rules, [ $id, $op, $val, $rule ];
16         }
17         $wfl{$name} = \@rules;
18 }
19
20 my @parts;
21 while (<>) {
22         my %p;
23         for my ($id, $val) (/(\w)=(\d+)/g) {
24                 $p{$id} = $val;
25         }
26         push @parts, \%p;
27 }
28
29 sub evaluate {
30         my ($part, $name) = @_;
31         my %seen;
32 NEWWFL:
33         return 0 if $seen{$name}++;
34         if ($name eq 'R') {
35                 return 0;
36         } elsif ($name eq 'A') {
37                 return sum values %$part;
38         }
39         my $w = $wfl{$name};
40         for my $rule (@$w) {
41                 my ($id, $op, $val, $nxt) = @$rule;
42
43                 if (!defined $op) {
44                         $name = $id;
45                         goto NEWWFL;
46                 } else {
47                         if ($op eq '<') {
48                                 if ($part->{$id} < $val) {
49                                         $name = $nxt;
50                                         goto NEWWFL;
51                                 }
52                         }
53                         if ($op eq '>') {
54                                 if ($part->{$id} > $val) {
55                                         $name = $nxt;
56                                         goto NEWWFL;
57                                 }
58                         }
59                 }
60         }
61 }
62
63 say sum map { evaluate($_, 'in') } @parts;