Re: [QUIZ] Perl 'Medium' Quiz of the Week #2005-05-06 - Ranges' Lookup
Yitzchak Scott-Thoennes <[email protected]> Sun, 15 May 2005 16:55:58 -0700
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Organization | bs"d |
| Message-ID | <[email protected]> |
On Fri, May 06, 2005 at 11:16:36PM +0300, Shlomi Fish wrote: > Well, the previous quiz did not seem to be very popular. Nor this one :) > $ret is a hash ref that should contain a field 'verdict' that is a boolean > specifying if any of the ranges contain $x. It may also contain 'match_set' > which points to a reference to a hash whose keys are the indexes of the > matching ranges. I wonder why match_set would be a hash. Oh well. The really neat way to solve this would be to return a tied, lazy verdict and match_set, that only do the work to the extent necessary, but I opted for a simple solution instead. I have the feeling that there's another optimization (other than sorting by one of the endpoints) that doesn't depend on having some clue about what kind of values are being dealt with, but couldn't bring it to the top of my mind.
qotw20050506.pl
(application/x-perl, 755 B)
sub prepare_ranges_handle {
[
# copy incoming data, lest caller change it
# and store as array of low value, high value, original index
map [@{$_[$_]}[0,1], $_],
# sort indicies by low value
sort {$_[$a][0] <=> $_[$b][0]}
0..$#_
]
}
sub lookup_ranges {
my $ranges = shift;
my $value = shift;
my %result = ( verdict => !1, match_set => {} );
for my $range (@$ranges) {
# give up if all following ranges begin above $value
last if $range->[0] > $value;
# is it in range?
if ($range->[1] >= $value) {
$result{verdict} = 1;
# record this range's original index as having matched
undef ${$result{match_set}}{$range->[2]};
}
}
\%result;
}
1;