--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.16;
+
+my %m;
+$; = ',';
+my $y = 0;
+my ($maxx, $maxy);
+while (<>) {
+ chomp;
+ my $x = 0;
+ $maxx = length;
+ for my $c (split //) {
+ $m{$x,$y}++ if $c eq '#';
+ $x++;
+ }
+ $y++;
+}
+$maxy = $y;
+
+my %gcd;
+sub gcd {
+ my ($n1, $n2) = @_;
+ return $gcd{$n1,$n2} //=
+ $n1 == $n2 ? $n1
+ : $n1 > $n2 ? gcd($n2, $n1-$n2)
+ : gcd($n1, $n2-$n1);
+}
+
+my %dir;
+sub dir1 {
+ my ($x, $y) = @_;
+ return (0, 1) if $x == 0 && $y > 0;
+ return (0,-1) if $x == 0 && $y < 0;
+ return (1, 0) if $y == 0 && $x > 0;
+ return (-1,0) if $y == 0 && $x < 0;
+ my $g = gcd(abs($x), abs($y));
+ return ($x/$g, $y/$g);
+}
+
+sub dir {
+ my ($x, $y) = @_;
+ $dir{$x,$y} //= [ dir1($x,$y) ];
+ return @{ $dir{$x,$y} };
+}
+
+my %sum;
+for (keys %m) {
+ my ($x,$y) = split /,/;
+ ASTEROID:
+ for (keys %m) {
+ my ($ax, $ay) = split /,/;
+ next if $ax == $x && $ay == $y;
+ say "testing $ax,$ay from $x,$y";
+ my ($dx, $dy) = dir($ax-$x, $ay-$y);
+ # next if $tried_dir{$dx,$dy}++;
+ say "dx,dy=$dx,$dy";
+ my ($x0, $y0) = ($x+$dx, $y+$dy);
+ while ($x0 != $ax || $y0 != $ay) {
+ say "x0,y0=$x0,$y0";
+ if ($m{$x0,$y0}) {
+ say "$ax,$ay cannot be seen from $x,$y because of $x0,$y0";
+ next ASTEROID;
+ }
+ $x0 += $dx; $y0 += $dy;
+ }
+ say "$ax,$ay CAN be seen from $x,$y";
+ $sum{$x,$y}++;
+ }
+}
+
+my @s = sort { $sum{$b} <=> $sum{$a} } keys %sum;
+say $s[0], '=', $sum{$s[0]};