Skip to content

Instantly share code, notes, and snippets.

@robin-a-meade
Created April 16, 2022 07:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robin-a-meade/5a21acc98705316796e3bb126b3cb571 to your computer and use it in GitHub Desktop.
Save robin-a-meade/5a21acc98705316796e3bb126b3cb571 to your computer and use it in GitHub Desktop.
Binary search in perl esp. for finding closest element
#!/bin/perl
# Binary search in perl
# https://www.perlmonks.org/?node_id=920127
# Useful for finding closest element
# https://www.perlmonks.org/?node_id=927656
sub _unsigned_to_signed { unpack('j', pack('J', $_[0])) }
sub binsearch(&$\@) {
my $compare = $_[0];
#my $value = $_[1];
my $array = $_[2];
my $i = 0;
my $j = $#$array;
return $j if $j == -1;
my $ap = do { no strict 'refs'; \*{caller().'::a'} }; local *$ap;
my $bp = do { no strict 'refs'; \*{caller().'::b'} }; local *$bp;
*$ap = \($_[1]);
for (;;) {
my $k = int(($i+$j)/2);
*$bp = \($array->[$k]);
my $cmp = $compare->()
or return $k;
if ($cmp < 0) {
$j = $k-1;
return _unsigned_to_signed(~$k) if $i > $j;
} else {
$i = $k+1;
return _unsigned_to_signed(~$i) if $i > $j;
}
}
}
my $value = 37;
my @array = (10, 20, 30, 40, 50, 60, 70, 80, 90, 100);
my $idx = binsearch { $a <=> $b } $value, @array;
splice(@array, ~$idx, 0, $value) if $idx < 0;
# Print the array
# https://stackoverflow.com/a/5741144
{local $,=', ';print @array}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment