Skip to content

Instantly share code, notes, and snippets.

@jaldhar
Created July 27, 2017 07:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaldhar/bae299ee03df93fcdd3633d751581e0b to your computer and use it in GitHub Desktop.
Save jaldhar/bae299ee03df93fcdd3633d751581e0b to your computer and use it in GitHub Desktop.
Trying to implement an iterator in Perl6
=begin pod
Algorithm::DawkinsWeasel is a simple model illustrating the idea of cumulative
selection in evolution.
The original form of it looked like this:
1. Start with a random string of 28 characters.
2. Make 100 copies of this string, with a 5% chance per character of that
character being replaced with a random character.
3. Compare each new string with "METHINKS IT IS LIKE A WEASEL", and give
each a score (the number of letters in the string that are correct and
in the correct position).
4. If any of the new strings has a perfect score (== 28), halt.
5. Otherwise, take the highest scoring string, and go to step 2
This module parametrizes the target string, mutation threshold, and number of
copies per round.
The goal is to be able to use it something like this:
my $weasel = Algorithm::DawkinsWeasel.new;
say $weasel.current-phrase while $weasel;
=end pod
unit class Algorithm::DawkinsWeasel:ver<0.0.2> does Iterator;
has Str @.target-phrase;
has Rat $.mutation-threshold;
has Int $.copies;
has Str @!charset;
has Int $!count;
has Str @!current-phrase;
has Int $!hi-score;
submethod BUILD(Str :$target-phrase = 'METHINKS IT IS LIKE A WEASEL',
Rat :$mutation-threshold = 0.05, Int :$copies = 100) {
@!target-phrase = $target-phrase.comb;
$!mutation-threshold = $mutation-threshold;
$!copies = $copies;
}
submethod TWEAK {
@!charset = | ['A' .. 'Z'] , ' ';
@!current-phrase = map { @!charset.pick }, 0 .. @!target-phrase.end;
$!hi-score = 0;
$!count = 0;
}
method evolve {
for (1 .. $!copies) {
my @trial = map {
1.rand < $!mutation-threshold ?? @!charset.pick !! $_;
}, @!current-phrase;
my Int $score = 0;
for 0 .. @!target-phrase.end -> $i {
if @trial[$i] eq @!target-phrase[$i] {
$score++;
}
}
if $score > $!hi-score {
$!hi-score = $score;
@!current-phrase = @trial;
}
}
}
method pull-one {
$!count++;
self.evolve;
return $!hi-score == @!target-phrase.elems ?? IterationEnd !! self;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment