2025 AoC Day 9 – Movie Theater

This is a solution to Advent of Code 2025 day 9, written in Raku.

https://adventofcode.com/2025/day/9

Part One

Using two red tiles as opposite corners, what is the largest area of any rectangle you can make?

use Test;

sub part-one($input) {
    my @coords = $input.IO.lines>>.split(',');
    my @areas = @coords.combinations(2).map(
        -> ($p1, $p2) {
            (abs($p2[0] - $p1[0]) + 1) * (abs(+$p2[1] - $p1[1]) + 1);
        });

    max(@areas);
}

is part-one('9-test.txt'), 50, 'test input';
{
    say part-one('9-input.txt');
    say "Took " ~ (now - ENTER now).base(10,2) ~ " seconds";
}
ok 1 - test input
4741848414
Took 1.26 seconds

Part Two

Using two red tiles as opposite corners, what is the largest area of any rectangle you can make using only red and green tiles?

use Test;

class CoordPair {
    has $.x1; has $.y1; has $.x2; has $.y2;
    method new($p1, $p2) {
        my $x1 = +$p1[0]; my $y1 = +$p1[1];
        my $x2 = +$p2[0]; my $y2 = +$p2[1];
        ($x1, $x2) = ($x2, $x1) if $x2 < $x1;
        ($y1, $y2) = ($y2, $y1) if $y2 < $y1;

        self.bless(:$x1, :$x2, :$y1, :$y2)
    }
}

class Area is CoordPair {
    has $.area;
    submethod TWEAK(:$x1, :$x2, :$y1, :$y2) {
        $!area = ($x2 - $x1 + 1) * ($y2 - $y1 + 1);
    }
}

sub part-two($input, :$svg) {
    my @coords = $input.IO.lines>>.split(',');

    my @lines = @coords.rotor(2 => -1);
    @lines.push((@coords[*-1], @coords[0]),);
    @lines .= map(-> ($p1, $p2) { CoordPair.new($p1, $p2) });

    my @horizontal = @lines.grep(-> $l { $l.y1 ==  $l.y2 });
    my @vertical = @lines.grep(-> $l { $l.x1 == $l.x2 });

    my @areas = @coords.combinations(2).map(
        -> ($p1, $p2) { Area.new($p1, $p2) }
    );

    AREA:
    for @areas.sort(-> $a { - $a.area }) -> $a {
        for @horizontal -> $l {
            next AREA if $a.x1 < $l.x2 and $a.x2 > $l.x1 and $a.y1 < $l.y1 < $a.y2;
        }
        for @vertical -> $l {
            next AREA if $a.y1 < $l.y2 and $a.y2 > $l.y1 and $a.x1 < $l.x1 < $a.x2;
        }

        if $svg {
            my ($x, $y) = @coords[*-1];
            my @path = "M {$x} {$y}";
            for @coords -> ($x2, $y2) { @path.push("L {$x2} {$y2}") }

            my $width = $a.x2 - $a.x1; my $height= $a.y2 - $a.y1;
            $svg.IO.spurt: qq:to/END/;
            <svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg">
              <g transform="scale(0.01)">
                <path d="@path.join(" ")" stroke="black" stroke-width="100" fill="transparent"/>
                <rect x="$a.x1()" y="$a.y1()" width="$width" height="$height"
                      stroke-width="100" fill="transparent" stroke="red"/>
              </g>
            </svg>
            END
        }
        return $a.area;
    }
}

is part-two('9-test.txt'), 24, 'test input';
{
    say "Part two: ", part-two('9-input.txt', svg => '9.svg');
    say "Took " ~ (now - ENTER now).base(10,2) ~ " seconds";
}
ok 1 - test input
Part two: 1508918480
Took 4.24 seconds

9.svg

raku