Games-LMSolve
view release on metacpan or search on metacpan
lib/Games/LMSolve/Plank/Base.pm view on Meta::CPAN
'type' => "array(start_end(xy(integer)))",
'required' => 1,
},
'layout' => { 'type' => "layout", 'required' => 1, },
};
my $input_obj = Games::LMSolve::Input->new();
my $input_fields = $input_obj->input_board( $filename, $spec );
my ( $width, $height ) =
@{ $input_fields->{'dims'}->{'value'} }{ 'x', 'y' };
my ( $goal_x, $goal_y );
if ( scalar( @{ $input_fields->{'layout'}->{'value'} } ) < $height )
{
die
"Incorrect number of lines in board layout (does not match dimensions";
}
my @board;
my $lines = $input_fields->{'layout'}->{'value'};
for ( my $y = 0 ; $y < $height ; $y++ )
{
my $l = [];
if ( length( $lines->[$y] ) < $width )
{
die "Too few characters in board layout in line No. "
. ( $input_fields->{'layout'}->{'line_num'} + $y + 1 );
}
my $x = 0;
foreach my $c ( split( //, $lines->[$y] ) )
{
push @$l, ( $c ne " " );
if ( $c eq "G" )
{
if ( defined($goal_x) )
{
die "Goal was defined twice!";
}
( $goal_x, $goal_y ) = ( $x, $y );
}
$x++;
}
push @board, $l;
}
if ( !defined($goal_x) )
{
die "The Goal was not defined in the layout";
}
my $planks_in = $input_fields->{'planks'}->{'value'};
my @planks;
my $get_plank = sub {
my $p = shift;
my ( $start_x, $start_y ) =
( $p->{'start'}->{'x'}, $p->{'start'}->{'y'} );
my ( $end_x, $end_y ) = ( $p->{'end'}->{'x'}, $p->{'end'}->{'y'} );
my $check_endpoints = sub {
if ( !$board[$start_y]->[$start_x] )
{
die "Plank cannot be placed at point ($start_x,$start_y)!";
}
if ( !$board[$end_y]->[$end_x] )
{
die "Plank cannot be placed at point ($end_x,$end_y)!";
}
};
my $plank_str = "Plank ($start_x,$start_y) ==> ($end_x,$end_y)";
if ( ( $start_x >= $width )
|| ( $end_x >= $width )
|| ( $start_y >= $height )
|| ( $end_y >= $height ) )
{
die "$plank_str is out of the boundaries of the board";
}
if ( $start_x == $end_x )
{
if ( $start_y == $end_y )
{
die "$plank_str has zero length!";
}
$check_endpoints->();
if ( $start_y > $end_y )
{
( $start_y, $end_y ) = ( $end_y, $start_y );
}
foreach my $y ( ( $start_y + 1 ) .. ( $end_y - 1 ) )
{
if ( $board[$y]->[$start_x] )
{
die "$plank_str crosses logs!";
}
}
return {
'len' => ( $end_y - $start_y ),
'start' => { 'x' => $start_x, 'y' => $start_y },
'dir' => "S"
};
}
elsif ( $start_y == $end_y )
{
$check_endpoints->();
if ( $start_x > $end_x )
{
( $start_x, $end_x ) = ( $end_x, $start_x );
}
foreach my $x ( ( $start_x + 1 ) .. ( $end_x - 1 ) )
{
if ( $board[$start_y]->[$x] )
{
die "$plank_str crosses logs!";
}
}
return {
'len' => ( $end_x - $start_x ),
'start' => { 'x' => $start_x, 'y' => $start_y },
'dir' => "E"
};
}
elsif ( ( $end_x - $start_x ) == ( $end_y - $start_y ) )
{
$check_endpoints->();
if ( $start_x > $end_x )
{
( $start_x, $end_x ) = ( $end_x, $start_x );
( $start_y, $end_y ) = ( $end_y, $start_y );
}
foreach my $i ( 1 .. ( $end_x - $start_x - 1 ) )
{
if ( $board[ $start_y + $i ]->[ $start_x + $i ] )
{
die "$plank_str crosses logs!";
}
}
if ( !grep { $_ eq "SE" } @{ $self->{'dirs'} } )
{
die "$plank_str is not aligned horizontally or vertically.";
}
return {
'len' => ( $end_x - $start_x ),
'start' => {
'x' => $start_x,
'y' => $start_y,
},
'dir' => "SE",
};
}
else
{
die "$plank_str is not aligned horizontally or vertically.";
}
};
foreach my $p (@$planks_in)
{
push @planks, $get_plank->($p);
}
$self->{'width'} = $width;
$self->{'height'} = $height;
$self->{'goal_x'} = $goal_x;
$self->{'goal_y'} = $goal_y;
$self->{'board'} = \@board;
$self->{'plank_lens'} = [ map { $_->{'len'} } @planks ];
my $state = [
0,
(
map {
(
$_->{'start'}->{'x'},
$_->{'start'}->{'y'},
(
( $_->{'dir'} eq "E" ) ? 0
: ( $_->{'dir'} eq "SE" ) ? 2
: 1
)
)
} @planks
)
];
$self->_process_plank_data($state);
( run in 1.498 second using v1.01-cache-2.11-cpan-39bf76dae61 )