aeinprst: 346
aeilprst: 344
adeiprst: 332
aeimprst: 328
####
use Algorithm::Combinatorics qw(:all);
my $iter = combinations_with_repetition(\@{['a'..'z']}, 8);
##
##
#! /usr/bin/perl
use threads;
use threads::shared;
use Thread::Semaphore;
use integer;
my $CORES = 8;
my $TOTAL :shared = 0;
my $TDONE :shared = 0;
my $tresh = 0;
my (%P, %N, @W, @N, %RES);
sub wfilt { tr/a-z//cd; length() <= 8; }
sub wval { my $x = 1; $x *= $P{$_} for split //; $x }
@P{'a'..'z'} = grep {(1x$_)!~/^(11+)\1+$/} 2..101;
open(WORDS, "words") or die;
@W = grep wfilt, ;
$N{&wval}++ for @W;
@N = keys %N;
my $SEM = Thread::Semaphore->new($CORES);
my @T = map threads->new(\&worker, $_), 'a'..'z';
report ((map {$_->join()} @T), 0);
sub x2 { map { my $t = $_; map {$t.$_} @_ } @_ }
sub worker {
my ($pivot) = @_; # aaaPzzzz
my (%A, %Z, @A, @Z, $a, $z);
$A{&wval} //= $_ for grep s/.$/$pivot/, x2(x2('a'..$pivot));
$Z{&wval} //= $_ for x2(x2($pivot..'z'));
@A = keys %A;
@Z = keys %Z;
report (-int(@A)*int(@Z));
for $a (@A) {
$SEM->down();
my @R;
for $z (@Z) {
my ($v, $n) = ($a*$z, 0);
$v % $_ or $n += $N{$_} for @N; # 99.99%
push @R, ($A{$a}.$Z{$z} => $n) if ($n > $tresh);
}
report (@R, int(@Z));
$SEM->up();
}
return (%RES);
}
sub report {
if ((my $n = pop) < 0) { lock($TOTAL); $TOTAL -= $n; }
else { lock($TDONE); $TDONE += $n; }
return unless @_;
%RES = (%RES, @_);
my @top = sort { $RES{$b} <=> $RES{$a} } keys %RES;
delete @RES{splice(@top, 20)} if @top > 20;
print "$_: $RES{$_}\n" for @top;
$tresh = $RES{pop @top};
no integer;
printf "! progress %d/%d (% 3.1f%%)\n@{['-'x40]}\n",
$TDONE, $TOTAL, 100.0*$TDONE/$TOTAL;
}