[Purdue-pm] fast table lookup of randomly associated items

Mark Senn mark at ecn.purdue.edu
Sat May 22 22:19:20 PDT 2010


I like this solution because it best echos the problem statement.
The __DATA__ section can be moved to a separate file if wanted.
-mark

#!/usr/bin/perl

use Modern::Perl;

my @table;
while (<DATA>)
{
    chomp;
    my ($range, $letter) = split /\s+/;
    ($range =~ /-/)  or  $range .= "-$range";
    my ($min, $max) = split /-/, $range;
    @table[$min..$max] = ($letter) x ($max-$min+1);
}

my $number = int 1 + rand $#table;
say "number $number is associated with $table[$number]";
__DATA__
1-5     A
6       B
7-12    C
13-20   D
21-25   E
26-30   F

> Say I have a table like the following:
> 
> number Item
> 1-5     A
> 6       B
> 7-12    C
> 13-20   D
> 21-25   E
> 26-30   F
> 
> Say I then have a random number generator that spits out a number
> from 1-30.
> 
> What is the fastest way to look up the item associated with that random
> number?
> 
> For more fun, say I want to store that table in a text file what is a
> good way to represent that?
> 
> I kicked around some ideas and the easiest solution I could come up with
> is the following. I settled on JSON since it's a bit more portable than
> most and I like its syntax better than YAML.
> ===================================
> 
> #!/usr/local/bin/perl
> 
> use 5.010;
> 
> use strict;
> use warnings;
> 
> use File::Slurp;
> use JSON;
> 
> my $table = q(table.json);
> my $json_text = read_file( $table ) ;
> my $data = from_json($json_text);
> 
> my $number = int(rand(30)+1);
> my $item = q(nothing);
> foreach my $row ( @$data ) {
>   if ( $number > $row->[0] ){
>   }
>   else {
>     $item = $row->[1];
>     last;
>   }
> }
> 
> say qq($number associated with $item);
> 
> exit(0);
> 
> ===================================
> table.json:
> 
> [
>  [5,"A"],
>  [6,"B"],
>  [12,"C"],
>  [20,"D"],
>  [25,"E"],
>  [30,"F"]
> ]


  And in a later message Joe wrote:
> Maybe fastest might be misnomer. I was hoping I could do something like:
> 
> my $random
> my ($key) = grep { $_ ~~ $random } keys %table;
> 
> I stumbled across something like this at stackoverflow but I can't find
> it now.
> 
> I was thinking that I could make the hash keys the range and then use
> smart matching to figure out which key the random number is in the range of.
> 
> Using ranges for hash keys does weird things however. Let alone that
> they don't get treated as a range in the smart match.
> 
> Well, to be honest I couldn't really get the ranges as keys thing
> working so I don't know if it would really treat the key as a range.
> 
> Maybe clever is what I'm looking for. :-)
> 
> >> For more fun, say I want to store that table in a text file what is a
> >> good way to represent that?
> > 
> >    I sort of liked your human readable format above.  JSON is fine but
> >    not as clear to the lay person.
> 
> I was using YAML for awhile but about 6 months or so ago I switched to
> JSON. It's easier for me to understand than YAML (which has some white
> space being important stuff that annoys me) is easily portable between
> langues (especially javascript since it is really just javascript).


More information about the Purdue-pm mailing list