use Sort::Packed 'sort_packed'; sub pwc_p { my ( $from, $to, $target ) = @_; use integer; my @witnesses = ([ 4, 7 ], [ 2 .. 9 ]); my ( %pairs, $j ); for ( my $i = ( $from + 2 ) / 3 * 3; $i <= $to; $i += 3 ) { sort_packed C => my $i_key = $i; my $k = $i % 9 ? 0 : 1; for ( @{ $witnesses[ $k ]}) { last if length( $j = $i * $_ ) != length( $i ); sort_packed C => my $j_key = $j; $pairs{ $i }{ $j } = $_ unless $i_key ne $j_key } for ( @{ $witnesses[ $k ]}) { last if length( $j = $i / $_ ) != length( $i ); next if $i % $_; sort_packed C => my $j_key = $j; $pairs{ $i }{ $j } = -$_ unless exists $pairs{ $j } && exists $pairs{ $j }{ $i } || $i_key ne $j_key } } return scalar grep { %$_ >= $target } values %pairs }