diff options
Diffstat (limited to 'lib/GridFiller/Chooser/Smarter.pm')
-rw-r--r-- | lib/GridFiller/Chooser/Smarter.pm | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/GridFiller/Chooser/Smarter.pm b/lib/GridFiller/Chooser/Smarter.pm new file mode 100644 index 0000000..814e930 --- /dev/null +++ b/lib/GridFiller/Chooser/Smarter.pm @@ -0,0 +1,118 @@ +package GridFiller::Chooser::Smarter; +use Moose; +use namespace::autoclean -also => [qw(maxfirst)]; +use GridFiller::Constants ':all'; +use List::Util 'reduce'; +use Carp; + +extends 'GridFiller::Chooser'; + +sub maxfirst { + return reduce { $a->[0] > $b->[0] ? $a : $b } @_; +} + +sub find_place_for { + my ($self,$word) = @_; + + my $length = length $word; + + my @candidates; + + push @candidates, $self->_find_places_horiz($length); + push @candidates, $self->_find_places_vert($length); + + return unless @candidates; + + my $ret = maxfirst @candidates; + + shift @$ret; + + return @$ret; +} + +sub _find_places_horiz { + my ($self,$length) = @_; + + my $rows = scalar @{$self->grid}; + my ($col,$space); + + my @ret; + + for my $row (0..$rows-1) { + ($space,$col) = $self->_find_in_row($row,$length); + push @ret, [$space,$col,$row,$HORIZONTAL] if defined $space; + } + return @ret; +} + +sub _find_places_vert { + my ($self,$length) = @_; + + my $cols = scalar @{$self->grid->[0]}; + my ($row,$space); + + my @ret; + + for my $col (0..$cols-1) { + ($space,$row) = $self->_find_in_col($col,$length); + push @ret,[$space,$col,$row,$VERTICAL] if defined $space; + } + return @ret; +} + +{ +my %symbols=( + $NOTHING => ' ', + $BLACK => 'X', + $WHITE => 'O', +); + +sub _do_find { + my ($self,$str,$length) = @_; + + my $rx = qr{\G .*? + (?: + X{$length} (?<tail>X*) + | + O{$length} (?<tail>O*) + ) }x; + + pos($str)=undef; + + my @ret; + + while ($str =~ m{$rx}gc) { + my $tail=length $+{tail}; + my $skip=pos($str)-$length-$tail; + + push @ret,[$tail,$skip]; + $self->log->debug(" skip $skip tail $tail") + } + + return unless @ret; + + return @{maxfirst(@ret)}; +} + +sub _find_in_row { + my ($self,$row,$length) = @_; + + my $str = join '',map { $symbols{$_} } @{$self->grid->[$row]}; + + $self->log->debug("row $row = $str"); + + return $self->_do_find($str,$length); +} + +sub _find_in_col { + my ($self,$col,$length) = @_; + + my $str = join '',map { $symbols{$_->[$col]} } @{$self->grid}; + + $self->log->debug("col $col = $str"); + + return $self->_do_find($str,$length); +} +} + +1; |