Je fonction, binary_range_search
, qui est appelé comme ceci:Comment étendre un itérateur de recherche binaire consommer plusieurs cibles
my $brs_iterator = binary_range_search(
target => $range, # eg. [1, 200]
search => $ranges # eg. [ {start => 1, end => 1000},
); # {start => 500, end => 1500} ]
brs_iterator->()
va parcourir toutes les @ gammes de $ sur quelle plage de $ chevauche.
Je voudrais étendre binary_range_search
pouvoir l'appeler avec plusieurs plages comme cible, par exemple:
target => $target_ranges # eg. [ [1, 200], [50, 300], ... ]
search => $search_ranges # as above
Ainsi, lorsque la recherche sur la gamme de $ -> [0] est épuisé, il se doit passez à $ range -> [1], et ainsi de suite. Voici la fonction en question, sous sa forme originale:
sub binary_range_search {
my %options = @_;
my $range = $options{target} || return;
my $ranges = $options{search} || return;
my ($low, $high) = (0, @{$ranges} - 1);
while ($low <= $high) {
my $try = int(($low + $high)/2);
$low = $try + 1, next if $ranges->[$try]{end} < $range->[0];
$high = $try - 1, next if $ranges->[$try]{start} > $range->[1];
my ($down, $up) = ($try) x 2;
my %seen =();
my $brs_iterator = sub {
if ( $ranges->[ $up + 1 ]{end} >= $range->[0]
and $ranges->[ $up + 1 ]{start} <= $range->[1]
and !exists $seen{ $up + 1 })
{
$seen{ $up + 1 } = undef;
return $ranges->[ ++$up ];
}
elsif ($ranges->[ $down - 1 ]{end} >= $range->[0]
and $ranges->[ $down + 1 ]{start} <= $range->[1]
and !exists $seen{ $down - 1 }
and $down > 0)
{
$seen{ $down - 1 } = undef;
return $ranges->[ --$down ];
}
elsif (!exists $seen{$try}) {
$seen{$try} = undef;
return $ranges->[$try];
}
else {
return;
}
};
return $brs_iterator;
}
return sub { };
}
C'est une stratégie de recherche binaire standard, jusqu'à ce qu'il trouve une zone de chevauchement. Il se déplace ensuite à droite, l'épuise, se déplace sur la gauche, l'épuise, et finalement abandonne. Idéalement, il faudrait alors shift
la prochaine plage cible, et refaire la recherche, je suppose (peut-être via la récursivité?). Mon problème est, je ne suis pas sûr de savoir comment faire ce travail avec la construction de l'itérateur.
C'est presque parfait; il ne m'est jamais venu à l'idée de simplement pousser les itérateurs sur une pile. La chose, cependant, est que l'itérateur retourné par cette fonction est ensuite utilisé comme entrée pour une fonction d'accumulateur. Je peux, bien sûr, changer l'accumulateur pour réutiliser plusieurs itérateurs. Merci!. –