Algorithm-MasterMind
view release on metacpan or search on metacpan
lib/Algorithm/MasterMind.pm view on Meta::CPAN
use lib qw( ../../lib ../lib ../../../lib );
# Module implementation here
sub new {
my $class = shift;
my $options = shift || croak "Need options here in Algorithm::MasterMind::New\n";
my $self = { _rules => [],
_evaluated => 0,
_hash_rules => {} };
bless $self, $class;
$self->initialize( $options );
return $self;
}
sub random_combination {
my $self = shift;
return random_string( $self->{'_alphabet'}, $self->{'_length'});
}
sub random_string {
my $alphabet = shift;
my $length = shift;
my $string;
my @alphabet = @{$alphabet};
for (my $i = 0; $i < $length; $i++ ) {
$string .= $alphabet[ rand( @alphabet) ];
}
return $string;
}
sub issue_first { #Default implementation
my $self = shift;
return $self->{'_last'} = $self->random_combination;
}
sub start_from {
my $class = shift;
my $options = shift || croak "Options needed to start!";
my $self = {};
bless $self, $class;
for my $o ( qw( consistent alphabet rules evaluated ) ) {
$self->{"_$o"} = $options->{$o};
}
return $self;
}
sub issue_first_Knuth {
my $self = shift;
my $string;
my @alphabet = @{ $self->{'_alphabet'}};
my $half = @alphabet/2;
for ( my $i = 0; $i < $self->{'_length'}; $i ++ ) {
$string .= $alphabet[ $i % $half ]; # Recommendation Knuth
}
$self->{'_first'} = 1; # Flag to know when the second is due
return $self->{'_last_string'} = $string;
}
sub issue_next {
croak "To be reimplemented in derived classes";
}
sub add_rule {
my $self = shift;
my ($combination, $result) = @_;
my %new_rule = %$result;
$new_rule{'combination'} = $combination;
push @{ $self->{'_rules'} }, \%new_rule;
}
sub feedback {
my $self = shift;
my ($result) = @_;
$self->add_rule( $self->{'_last'}, $result );
}
sub number_of_rules {
my $self= shift;
return scalar @{ $self->{'_rules'}};
}
sub rules {
my $self= shift;
return $self->{'_rules'};
}
sub evaluated {
my $self=shift;
return $self->{'_evaluated'};
}
sub matches {
my $self = shift;
my $string = shift || croak "No string\n";
my @rules = @{$self->{'_rules'}};
my $result = { matches => 0,
result => [] };
# print "Checking $string, ", $self->{'_evaluated'}, "\n";
for my $r ( @rules ) {
my $rule_result = $self->check_rule( $r, $string );
$result->{'matches'}++ if ( $rule_result->{'match'} );
push @{ $result->{'result'} }, $rule_result;
}
$self->{'_evaluated'}++;
return $result;
}
sub check_rule {
my $self = shift;
my $rule = shift;
my $string = shift;
if ( ! $self->{'_rules_hash'}->{ $rule->{'combination'} }{ $string } ) {
my $result = check_combination( $rule->{'combination'}, $string );
lib/Algorithm/MasterMind.pm view on Meta::CPAN
my $self = shift;
my $length = $self->{'_length'};
my @responses_array = variations_with_repetition( ['B', 'W', '-'],
$length );
my %responses;
for my $r ( @responses_array ) {
my %partial = ( W => 0,
B => 0 );
for my $c (@$r) {
$partial{$c}++;
}
$responses{$partial{'B'}."B-".$partial{'W'}."W"} = 1;
}
# Delete impossible
my $impossible = ($length-1)."B-1W";
delete $responses{$impossible};
my @possible_responses = sort keys %responses;
return @possible_responses;
}
sub entropy {
my $combination = shift;
my %freqs;
map( $freqs{$_}++, split( //, $combination));
my $entropy;
for my $k (keys %freqs ) {
my $probability = $freqs{$k}/length($combination);
$entropy -= $probability * log ($probability);
}
return $entropy;
}
sub response_as_string {
return $_[0]->{'blacks'}."b-".$_[0]->{'whites'}."w";
}
"4 blacks, 0 white"; # Magic true value required at end of module
__END__
=head1 NAME
Algorithm::MasterMind - Framework for algorithms that solve the MasterMind game
=head1 VERSION
This document describes Algorithm::MasterMind version 0.4.1
=head1 SYNOPSIS
use Algorithm::MasterMind;
use Algorithm::MasterMind::Solver; # Change "solver" to your own.
my $solver = new Algorithm::MasterMind::Solver $options;
my $first_string = $solver->issue_first();
$solver->feedback( check_combination( $secret_code, $first_string) );
my $played_string = $solver->issue_next;
$solver->feedback( check_combination( $secret_code, $played_string) );
#And so on until solution is found
=head1 DESCRIPTION
Includes common functions used in Mastermind solvers; it should not be
used directly, but from derived classes. See examples in
L<Algorithm::MasterMind::Random>, for instance.
=head1 INTERFACE
=head2 new ( $options )
Normally to be called from derived classes
=head2 add_rule( $combination, $result)
Adds a rule (set of combination and its result as a hash) to the set
of rules. These rules represent the information we've got on the
secret code.
=head2 check_combination( $secret_code, $combination )
Checks a combination against the secret code, returning a hashref with
the number of blacks (correct in position) and whites (correct in
color, not position)
=head2 distance( $object )
Computes distance to a consistent combination, computed as the number
of blacks and whites that need change to become a consistent
combination.
=head2 check_combination_old ( $secret_code,
$combination )
Old way of checking combinations, eliminated after profiling
=head2 check_rule ($rule, $combination)
Same as C<check_combination>, except that a rule contains a
combination and how it scored against the secret code
=head2 issue_first ()
Issues the first combination, which might be generated in a particular
way
=head2 start_from ()
Used when you want to create an solver once it's been partially
solved; it contains partial solutions.
=head2 issue_first_Knuth
First combination looking like AABC for the normal
mastermind. Proposed by Knuth in one of his original papers.
=head2 issue_next()
Issues the next combination
=head2 feedback()
Obtain the result to the last combination played
=head2 guesses()
Total number of guesses
=head2 evaluated()
Total number of combinations checked to issue result
=head2 number_of_rules ()
Returns the number of rules in the algorithm
=head2 rules()
Returns the rules (combinations, blacks, whites played so far) as a
reference to array
=head2 matches( $string )
Returns a hash with the number of matches, and whether it matches
every rule with the number of blacks and whites it obtains with each
of them
=head2 hashify ( $string )
Turns a string into a hash, to help with comparisons. Used internally,
mainly.
=head2 not_in_combination( $string)
Returns the letters from the alphabet that are _not_ in this
combination. Might be useful for certain strategies.
=head2 random_combination
Combines randomly the alphabet, issuing, you guessed it, a random
( run in 0.908 second using v1.01-cache-2.11-cpan-39bf76dae61 )