--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.40;
+
+my ($x, $y);
+my @map;
+while (<>) {
+ chomp;
+ last if /^$/;
+ if (/@/g) { $x = pos()-1; $y = $.-1; }
+ push @map, [ split // ];
+}
+
+my $xmax = $#{ $map[0] };
+my $ymax = $#map;
+
+my %dir = (
+ '^' => [ 0, -1 ],
+ '<' => [ -1, 0 ],
+ '>' => [ 1, 0 ],
+ 'v' => [ 0, 1 ],
+);
+
+while (<>) {
+ chomp;
+ for my $d (split //) {
+ my ($dx, $dy) = $dir{$d}->@*;
+ my ($x1, $y1) = ($x+$dx, $y+$dy);
+ my ($nx, $ny) = ($x+$dx, $y+$dy);
+ while (1) {
+ last if $map[$ny][$nx] eq '#';
+ if ($map[$ny][$nx] eq '.') {
+ if ($map[$y1][$x1] eq 'O') {
+ $map[$ny][$nx] = 'O';
+ }
+ $map[$y][$x] = '.';
+ $map[$y1][$x1] = '@';
+ $x = $x1;
+ $y = $y1;
+ last;
+ }
+ $nx += $dx;
+ $ny += $dy;
+ }
+ }
+}
+
+my $sum;
+for my $y (0 .. $ymax) {
+ for my $x (0 .. $xmax) {
+ if ($map[$y][$x] eq 'O') {
+ $sum += 100*$y+$x;
+ }
+ print $map[$y][$x];
+ }
+ print "\n";
+}
+
+say $sum;
+
--- /dev/null
+#!/usr/bin/perl -w
+
+use v5.40;
+
+my ($x, $y);
+my @map;
+while (<>) {
+ chomp;
+ last if /^$/;
+ s/#/##/g;
+ s/\./../g;
+ s/O/[]/g;
+ s/@/@./g;
+ if (/@/g) { $x = pos()-1; $y = $.-1; }
+ push @map, [ split // ];
+}
+
+my $xmax = $#{ $map[0] };
+my $ymax = $#map;
+
+say "start at $x,$y";
+
+my %dir = (
+ '^' => [ 0, -1 ],
+ '<' => [ -1, 0 ],
+ '>' => [ 1, 0 ],
+ 'v' => [ 0, 1 ],
+);
+
+sub can_move {
+ my ($x, $y, $dx, $dy) = @_;
+
+ my $nx = $x+$dx;
+ my $ny = $y+$dy;
+ my $m = $map[$ny][$nx];
+
+ return () if $m eq '#';
+ return [$x,$y] if $m eq '.';
+
+ my (@r1, @r2);
+ if ($dy) {
+ if ($m eq '[') {
+ @r1 = can_move($nx, $ny, $dx, $dy);
+ @r2 = can_move($nx+1, $ny, $dx, $dy);
+ } elsif ($map[$ny][$nx] eq ']') {
+ @r1 = can_move($nx, $ny, $dx, $dy);
+ @r2 = can_move($nx-1, $ny, $dx, $dy);
+ }
+ if (@r1 && @r2) {
+ return ([$x, $y], @r1, @r2);
+ } else {
+ return ();
+ }
+ } else {
+ if ($dx == 1) {
+ my @rv = can_move($nx+1, $ny, $dx, $dy);
+ if (@rv) {
+ return ([$x, $y], [$x+1, $y], @rv);
+ } else {
+ return ();
+ }
+ } else {
+ my @rv = can_move($nx-1, $ny, $dx, $dy);
+ if (@rv) {
+ return ([$x,$y], [$x-1, $y], @rv);
+ } else {
+ return ();
+ }
+ }
+ }
+}
+
+while (<>) {
+ chomp;
+ for my $d (split //) {
+ my ($dx, $dy) = $dir{$d}->@*;
+ my @rv = can_move($x, $y, $dx, $dy);
+ my %seen;
+ for my $obj (reverse @rv) {
+ my ($x, $y) = @$obj;
+ next if $seen{"$x,$y"}++;
+ my $nx = $x+$dx;
+ my $ny = $y+$dy;
+ # say "moving $x,$y to $nx,$ny $map[$y][$x]";
+ $map[$ny][$nx] = $map[$y][$x];
+ $map[$y][$x] = '.';
+ }
+ if (@rv) {
+ $x += $dx; $y += $dy;
+ }
+ }
+}
+
+my $sum;
+for my $y (0 .. $ymax) {
+ for my $x (0 .. $xmax) {
+ if ($map[$y][$x] eq '[') {
+ $sum += 100*$y+$x;
+ }
+ print $map[$y][$x];
+ }
+ print "\n";
+}
+
+say $sum;
+