Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use strict;
- use warnings;
- use feature qw(say);
- use List::AllUtils qw(max min minmax);
- $| = 1;
- my @input = map { chomp; [map {int} split /,/] } <>;
- my %horz;
- my %vert;
- my @lines;
- for (my $i = -1; $i < $#input; $i++) {
- my @x = minmax ($input[$i][0], $input[$i+1][0]);
- my @y = minmax ($input[$i][1], $input[$i+1][1]);
- push( @lines, [[$x[0],$y[0]], [$x[1],$y[1]]] );
- # ASSERT: Assuming only 1 interval in a given row or col (so no list needed)
- # ASSERT: None of these are adjacent and parallel, forming a 0-width channel
- if ($input[$i][1] == $input[$i+1][1]) {
- $horz{$input[$i][1]}->@* = @x;
- } else {
- $vert{$input[$i][0]}->@* = @y;
- }
- }
- my @vertKeys = sort {$a<=>$b} keys %vert;
- sub inside {
- my @pt = @_;
- my $cross = 0;
- return (1) if (exists $horz{$pt[1]} and ($horz{$pt[1]}[0] <= $pt[0] <= $horz{$pt[1]}[1]));
- return (1) if (exists $vert{$pt[0]} and ($vert{$pt[0]}[0] <= $pt[1] <= $vert{$pt[0]}[1]));
- foreach my $x (@vertKeys) {
- last if ($x > $pt[0]);
- if ($vert{$x}[0] < $pt[1] < $vert{$x}[1]) {
- # cross middle
- $cross++;
- } elsif ($vert{$x}[0] == $pt[1]) {
- # hit top
- my @hline = $horz{$pt[1]}->@*;
- my $other = ($hline[0] != $pt[0]) ? $hline[0] : $hline[1];
- $cross-- if ($vert{$other}[0] == $pt[1]);
- } elsif ($vert{$x}[1] == $pt[1]) {
- # hit bottom
- my @hline = $horz{$pt[1]}->@*;
- my $other = ($hline[0] != $pt[0]) ? $hline[0] : $hline[1];
- $cross-- if ($vert{$other}[1] == $pt[1]);
- }
- }
- return ($cross % 2);
- }
- my $part1 = 0;
- my $part2 = 0;
- for (my $i = 0; $i < @input; $i++) {
- BOX:
- for (my $j = -1; $j < $i; $j++) {
- my $area = (abs($input[$i][0] - $input[$j][0]) + 1)
- * (abs($input[$i][1] - $input[$j][1]) + 1);
- $part1 = max ($area, $part1);
- next if ($area < $part2);
- next if (!&inside($input[$i][0], $input[$j][1]) or !&inside($input[$j][0], $input[$i][1]));
- my @x = minmax ($input[$i][0], $input[$j][0]);
- my @y = minmax ($input[$i][1], $input[$j][1]);
- my @rect = ([$x[0]+1, $y[0]+1], [$x[1]-1, $y[1]-1]);
- next if ($rect[1][0] < $rect[0][0] or $rect[1][1] < $rect[0][1]);
- foreach my $line (@lines) {
- my @inter = ([max ($rect[0][0], $line->[0][0]), max ($rect[0][1], $line->[0][1])],
- [min ($rect[1][0], $line->[1][0]), min ($rect[1][1], $line->[1][1])]);
- next BOX if ($inter[0][0] <= $inter[1][0] and $inter[0][1] <= $inter[1][1]);
- }
- if ($area > $part2) {
- say "[$i]\t$area";
- $part2 = $area;
- }
- }
- }
- say "Part 1: $part1";
- say "Part 2: $part2";
Advertisement
Add Comment
Please, Sign In to add comment