Acme-Partitioner
view release on metacpan or search on metacpan
lib/Acme/Partitioner.pm view on Meta::CPAN
package Acme::Partitioner;
use 5.012000;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our %EXPORT_TAGS = ( 'all' => [ qw(
) ] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = qw(
);
our $VERSION = '0.01';
sub using {
my ($class, @list) = @_;
bless {
by_string => { map { $_ => 0 } @list },
sublists => [\@list],
}, $class;
}
sub once_by {
my ($self, $sub) = @_;
Acme::Partitioner::Actor::_new(undef, "once", $sub, $self);
}
sub partition_of {
my ($self, $item) = @_;
$self->{by_string}{$item};
}
sub items_in {
my ($self, $partition) = @_;
@{ $self->{sublists}[$partition] }
}
sub size {
my ($self) = @_;
scalar @{ $self->{sublists} }
}
sub all_partitions {
my ($self) = @_;
map { [@$_] } @{ $self->{sublists} }
}
package Acme::Partitioner::Actor;
use 5.012000;
use strict;
use warnings;
sub _new {
my ($old, $type, $sub, $partitioner) = @_;
$partitioner //= $old->{partitioner};
bless {
partitioner => $partitioner,
subs => [
($old ? @{ $old->{subs} } : ()),
[$type, $sub],
],
}, __PACKAGE__
}
sub once_by {
my ($self, $sub) = @_;
_new($self, "once", $sub);
}
sub then_by {
my ($self, $sub) = @_;
_new($self, "then", $sub);
}
sub refine {
my ($self) = @_;
unless (@{ $self->{subs} }) {
warn "Attempt to refine partitions without active refiners";
return;
}
my $old_size = $self->{partitioner}->size();
my $next_id = $old_size;
for (my $ix = 0; $ix < @{ $self->{subs} }; ++$ix) {
my @temp;
for my $sublist (@{ $self->{partitioner}{sublists} }) {
my %h;
for my $item (@{ $sublist }) {
local $_ = $item;
my $key = $self->{subs}[$ix][1]->($item);
push @{ $h{$key} }, $item;
}
push @temp, values %h;
}
#################################################################
#
#################################################################
my %occupied;
my @new_list;
for (my $ix = 0; $ix < @temp; ++$ix) {
my $first = $temp[$ix]->[0];
my $first_id = $self->{partitioner}->partition_of($first) // 0;
if (not $occupied{ $first_id }++) {
$new_list[ $first_id ] = $temp[$ix];
next;
}
my $new_id = $next_id++;
$new_list[ $new_id ] = $temp[$ix];
$self->{partitioner}{by_string}{$_} = $new_id
for @{ $temp[$ix] };
}
( run in 0.659 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )