### re: AoC Day 13: Mine Cart Madness VIEW POST

Perl solution. Most of the decisions are represented by the hash tables at the beginning of the code:

``````#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use List::Util qw{ first };

use enum qw( X Y FACING TURN );
use enum qw( LEFT STRAIGHT RIGHT );
use constant {
MOVE => {
'<' => [ -1,  0 ],
'>' => [  1,  0 ],
'v' => [  0,  1 ],
'^' => [  0, -1 ],
},
BEND => {
'^/'  => '>',
'^\\' => '<',
'v/'  => '<',
'v\\' => '>',
'</'  => 'v',
'<\\' => '^',
'>/'  => '^',
'>\\' => 'v',
},
FACES => [ '^', '>', 'v', '<' ],
};

my (@map, @carts, %crash);
while (<>) {
chomp;
while (/([<>^v])/g) {
push @carts, [ pos() - 1, \$. - 1, \$1, LEFT ];
++\$crash{ \$carts[-1][X] }{ \$carts[-1][Y] };
}
s/[<>]/-/g;
s/[v^]/|/g;
push @map, [split //, \$_, -1];
}

while (1) {
for my \$cart (
sort { \$a->[Y] <=> \$b->[Y] || \$a->[X] <=> \$b->[X] } @carts
) {
--\$crash{ \$cart->[X] }{ \$cart->[Y] };
my \$move = MOVE->{ \$cart->[FACING] };
\$cart->[\$_] += \$move->[\$_] for X, Y;
if (\$crash{ \$cart->[X] }{ \$cart->[Y] }++) {
say "\$cart->[X],\$cart->[Y]";
exit
}

my \$current = \$map[ \$cart->[Y] ][ \$cart->[X] ];
next if \$current =~ /[-|]/;

if ('+' eq \$current) {
my \$face_index = first { \$cart->[FACING] eq FACES->[\$_] }
0 .. \$#{(FACES)};
\$face_index += (-1, 0, 1)[ \$cart->[TURN] ];
\$cart->[FACING] = FACES->[ \$face_index % 4 ];
++\$cart->[TURN];
\$cart->[TURN] %= 3;

} else {
\$cart->[FACING] = BEND->{ \$cart->[FACING] . \$current };
}
}
}
``````

In part 2, I just replaced the code that printed the collision with a new one that removes the two carts involved.

``````#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use List::Util qw{ first };

use enum qw( X Y FACING TURN );
use enum qw( LEFT STRAIGHT RIGHT );
use constant {
MOVE => {
'<' => [ -1,  0 ],
'>' => [  1,  0 ],
'v' => [  0,  1 ],
'^' => [  0, -1 ],
},
BEND => {
'^/'  => '>',
'^\\' => '<',
'v/'  => '<',
'v\\' => '>',
'</'  => 'v',
'<\\' => '^',
'>/'  => '^',
'>\\' => 'v',
},
FACES => [ '^', '>', 'v', '<' ],
};

my @map;
my @carts;
my %crash;
while (<>) {
chomp;
while (/([<>^v])/g) {
push @carts, [ pos() - 1, \$. - 1, \$1, LEFT ];
++\$crash{ \$carts[-1][X] }{ \$carts[-1][Y] };
}
s/[<>]/-/g;
s/[v^]/|/g;
push @map, [split //, \$_, -1];
}

while (1) {
for my \$cart (
sort { \$a->[Y] <=> \$b->[Y] || \$a->[X] <=> \$b->[X] } @carts
) {
next unless \$cart->[FACING];

--\$crash{ \$cart->[X] }{ \$cart->[Y] };
my \$move = MOVE->{ \$cart->[FACING] };
\$cart->[\$_] += \$move->[\$_] for X, Y;
if (\$crash{ \$cart->[X] }{ \$cart->[Y] }++) {
\$crash{ \$cart->[X] }{ \$cart->[Y] } -= 2;
\$cart->[FACING] = 0;
my \$other_cart = first {
\$_->[FACING] && \$_->[X] == \$cart->[X] && \$_->[Y] == \$cart->[Y]
} @carts;
\$other_cart->[FACING] = 0;
next
}

my \$current = \$map[ \$cart->[Y] ][ \$cart->[X] ];
next if \$current =~ /[-|]/;

if ('+' eq \$current) {
my \$face_index = first { \$cart->[FACING] eq FACES->[\$_] }
0 .. \$#{(FACES)};
\$face_index += (-1, 0, 1)[ \$cart->[TURN] ];
\$cart->[FACING] = FACES->[ \$face_index % 4 ];
++\$cart->[TURN];
\$cart->[TURN] %= 3;

} else {
\$cart->[FACING] = BEND->{ \$cart->[FACING] . \$current };
}
}

my @left = grep \$carts[\$_][FACING], 0 .. \$#carts;
next unless 1 == @left;

say join ',', @{ \$carts[ \$left ] }[X, Y];
exit
}
``````
code of conduct - report abuse  