package Games::Nonogram::BruteForce; use strict; use warnings; use Storable (); sub run { my ($class, $grid) = @_; my $data = _freeze( $grid ); return if $grid->stash->{bruteforce}->{$data}; $grid->stash->{bruteforce}->{$data} = 1; $grid->log( "Start brute forcing" ); my ($target, $free); foreach my $clue ( $grid->clues ) { next if $clue->is_done; if ( !$free or $free > $clue->{free} ) { $free = $clue->{free}; $target = $clue; } } return unless $target; # should be solved already $grid->log( "target: ", $target->id ); my @candidates = $target->candidates; foreach my $candidate ( @candidates ) { $target->line->as_vec( $candidate ); $grid->update; eval { my $str = ''; my $prev = $grid->as_string; while( $str ne $prev and !$grid->is_done ) { $grid->update; $prev = $str; $str = $grid->as_string; $grid->log( $str ) if $grid->debug; } if ( $grid->is_done ) { $grid->log( "Found an answer" ); push @{ $grid->stash->{answers} ||= [] }, $str; } else { $class->run( $grid ); } }; if ( $@ ) { $grid->log( "Skip" ); } _thaw( $grid, $data ); } } sub _freeze { my $grid = shift; my @data; foreach my $clue ( $grid->clues ) { push @data, $clue->line->as_vec; } return Storable::freeze( \@data ); } sub _thaw { my ($grid, $data) = @_; my @data = @{ Storable::thaw( $data ) }; foreach my $clue ( $grid->clues ) { $clue->reset_blocks; $clue->line->as_vec( shift @data ); } } 1; __END__ =head1 NAME Games::Nonogram::BruteForce =head1 SYNOPSIS use Games::Nonogram::BruteForce; Games::Nonogram::BruteForce->run($grid); =head1 DESCRIPTION Even the simplest Nonogram may require brute force to solve it. The best known and smallest one looks like below: 1 1 1 _ _ 1 _ _ This module is used internally to try all (but hopefully least) possibilities of the puzzle, after every other means. =head1 METHOD =head2 run takes a puzzle grid and sets possible solutions to the stash of the grid. If this fails, the puzzle is probably broken... or is too large to solve on the memory. =head1 AUTHOR Kenichi Ishigaki, Eishigaki at cpan.orgE =head1 COPYRIGHT AND LICENSE Copyright 2007 by Kenichi Ishigaki This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut