Iterator-Flex
view release on metacpan or search on metacpan
lib/Iterator/Flex/Permute.pm view on Meta::CPAN
package Iterator::Flex::Permute;
# ABSTRACT: Permute Iterator Class
use v5.28;
use strict;
use warnings;
use experimental qw( signatures postderef declared_refs );
our $VERSION = '0.34';
use parent 'Iterator::Flex::Base';
use Iterator::Flex::Utils qw( :IterAttrs :IterStates throw_failure );
use Iterator::Flex::Factory 'to_iterator';
use Scalar::Util;
use Ref::Util 'is_hashref', 'is_arrayref';
use namespace::clean;
sub new ( $class, $array, $pars = {} ) {
throw_failure( parameter => q{'array' argument must be an array} )
unless is_arrayref( $array );
throw_failure( parameter => q{'pars' argument must be a hash} )
unless is_hashref( $pars );
my %pars = $pars->%*;
my $k = delete $pars{k} // $array->@*;
my $n = $array->@*;
defined $k && Scalar::Util::looks_like_number( $k ) && int( $k ) == $k && $k > 0
|| throw_failure( parameter => 'k parameter is not a positive integer' );
throw_failure( parameter => "size of subset (k = $k) > size of set ( $n )" )
if $k > $n;
$class->SUPER::new( { k => $k, array => $array, }, \%pars );
}
my sub permutations;
sub construct ( $class, $state ) {
throw_failure( parameter => q{state must be a HASH reference} )
unless Ref::Util::is_hashref( $state );
my ( $array, $k, $idx, $value, $c, $i, $restart ) = @{$state}{
qw[ array k idx value
c i restart
] };
$value //= [];
$c //= [ ( 0 ) x $k ];
$i //= 1;
$restart //= !!0;
my $self;
my $iterator_state;
my $n = $array->@*;
my %params = (
( +_SELF ) => \$self,
( +STATE ) => \$iterator_state,
( +CURRENT ) => sub {
return $idx ? [ $value->@* ] : undef;
},
( +RESET ) => sub {
$i = 1;
$c = [ ( 0 ) x $k ];
$restart = !!0;
$idx = undef;
$value->@* = ();
},
+( REWIND ) => sub {
$i = 1;
$c = [ ( 0 ) x $k ];
$restart = !!0;
$idx = undef;
},
);
if ( $n == $k ) {
$params{ +NEXT } = sub {
return $self->signal_exhaustion
if $iterator_state == IterState_EXHAUSTED;
my \@value = $value;
my \@array = $array;
if ( !defined $idx ) {
$idx = [ 0 .. $k - 1 ];
}
else {
$i = permutations( $c, $i, $n, $idx, $restart );
return $self->signal_exhaustion if !defined $i;
( run in 0.661 second using v1.01-cache-2.11-cpan-6aa56a78535 )