]> www.fi.muni.cz Git - aoc2021.git/blob - 44.pl
Day 25: pretty straightforward
[aoc2021.git] / 44.pl
1 #!/usr/bin/perl -w
2
3 use v5.16;
4
5 $; = ',';
6 my @cuboids;
7 while (<>) {
8         my $state = /^on / ? 1 : 0;
9         my ($xmin, $xmax, $ymin, $ymax, $zmin, $zmax) = /-?\d+/g;
10         ($xmin, $xmax) = ($xmax, $xmin) if $xmax < $xmin;
11         ($ymin, $ymax) = ($ymax, $ymin) if $ymax < $ymin;
12         ($zmin, $zmax) = ($zmax, $zmin) if $zmax < $zmin;
13         push @cuboids, [$xmin, $xmax, $ymin, $ymax, $zmin, $zmax, $state];
14 }
15
16 sub overlaps_int {
17         my ($min1, $max1, $min2, $max2) = @_;
18         return ($min1 >= $min2 && $min1 <= $max2)
19                 || ($max1 >= $min2 && $max1 <= $max2)
20                 || ($min1 <= $min2 && $max1 >= $max2)
21                 || ($min1 >= $min2 && $max1 <= $max2);
22 }
23
24 sub overlaps_axis {
25         my ($c1, $c2, $axis) = @_;
26         $axis *=2;
27         return overlaps_int($c1->[$axis], $c1->[$axis+1], $c2->[$axis], $c2->[$axis+1]);
28 }
29
30 my @on_cuboids;
31 for my $c1 (@cuboids) {
32         my @on_new;
33         CUBOID:
34         while (@on_cuboids) {
35                 my $c2 = shift @on_cuboids;
36                 for (0 .. 2) { # does $c1 overlap $c2?
37                         if (!overlaps_axis($c1, $c2, $_)) {
38                                 push @on_new, $c2;
39                                 next CUBOID;
40                         }
41                 }
42                 for (0 .. 2) {
43                         my ($min, $max) = (2*$_, 2*$_+1);
44                         if ($c1->[$min] > $c2->[$min] && $c1->[$min] <= $c2->[$max]) {
45                                 my @c = @$c2;
46                                 $c[$max] = $c1->[$min]-1;
47                                 push @on_cuboids, [ @c ];
48                                 @c = @$c2;
49                                 $c[$min] = $c1->[$min];
50                                 push @on_cuboids, [ @c ];
51                                 next CUBOID;
52                         }
53                         if ($c1->[$max] >= $c2->[$min] && $c1->[$max] < $c2->[$max]) {
54                                 my @c = @$c2;
55                                 $c[$max] = $c1->[$max];
56                                 push @on_cuboids, [ @c ];
57                                 @c = @$c2;
58                                 $c[$min] = $c1->[$max]+1;
59                                 push @on_cuboids, [ @c ];
60                                 next CUBOID;
61                         }
62                         if ($c1->[$min] > $c2->[$min]
63                                 || $c1->[$max] < $c2->[$max]) {
64                                 push @on_new, $c2;
65                                 next CUBOID;
66                         }
67                 }
68         }
69         push @on_new, $c1 if $c1->[6];
70         @on_cuboids = @on_new;
71 }
72
73 my $count;
74 for my $c1 (@on_cuboids) {
75         $count += ($c1->[1] - $c1->[0] + 1)
76                 * ($c1->[3] - $c1->[2] + 1)
77                 * ($c1->[5] - $c1->[4] + 1);
78 }
79
80 say $count;