Turning number ranges into prefixes

McGlinchy, Alistair Alistair.McGlinchy at marks-and-spencer.com
Thu Aug 24 15:52:42 BST 2006


Dave et al,

A few comments about your solution. I have a different solution below.
> my @minprefixes = map { substr($min, 0, $_) } reverse 1..length($min);
> my @maxprefixes = map { substr($max, 0, $_) } reverse 1..length($max);
> my $longest_prefix;
> foreach(0 .. length($max) - 1) {
>     if($minprefixes[$_] == $maxprefixes[$_]) {
>         $longest_prefix = $minprefixes[$_];
>         last;
>     }
> }

As commented earlier. This can be obfu^Wsimplified by these two lines
("$min" ^ "$max") =~  /(^\0*)/;
my $longest_prefix = substr($min,0,length $1);

>     my $extradigits = length($min) - length($prefix);
>     return () unless($extradigits);	
This is bugged. $extradigits can legally be 0. Consider $min =1 and $max
=2.
   
>     if(
>         $prefix.('0' x $extradigits) >= $min &&
>         $prefix.('9' x $extradigits) <= $max
I'm sure there are some optimisations possible here too. Eg
	($prefix  ge $min)  is the same as the first clause isn't it?

Now my solution. I approached this problem from a more text based
solution allowing for variable length phone number prefixes. Eg phone
numbers from 141xxxx to 1541yyyyy.  More comments inline.

Cheers

Alistair


__CODE__

my $min = 141;  # same as 1410000000...
my $max = 1541; # same as 1541999999...

print "Min: $min, Max: $max\n";
("$min" ^ "$max") =~  /(^\0*)/;
my $longest_prefix = substr($min,0,length $1);
print "Longest prefix: $longest_prefix\n";

my @results;
my $last_char;

# Pop each char off $min and add all suffixes up to 9 into result
push @results,$min;
while (length($min) > length($longest_prefix)+1) {
    push @results,  map {$min.$_} (chop $min)+1 .. 9;
}
# Repeat with $max,
push @results, $max;
while (length($max) > length($longest_prefix)+1) {
    push @results,  map {$max.$_} 0 .. (chop $max) -1 ;
}
# Fill in the middle bit between what's left of $min and $max 
push @results, map {$longest_prefix.$_} ( (chop $min) + 1 .. (chop
$max)-1);

# The sort here is just being lazy, it is possible to add all the above
entries 
# into @results in the right order first time round if the code were
reordered
# and a few more temp vars included.
@results= sort @results;  

# optimise results to remove suffixes with all 10 possible entries
# xxxxxx0, xxxxxx1, ... xxxxxx9 
# I tried to do this automatically within the above code but couldn't 
# get it to work without recursion.

for (my $i =0; $i< @results -9; $i++) {
    if (
            (substr($results[$i],-1,1) eq 0) and  # The last char is 0
            ($results[$i+ 9]  == $results[$i]+9)  # 10th pos is 9 ahead
        ) {
            my $opt_val = substr($results[$i],0,-1);
            splice(@results,$i, 10, $opt_val);
            $i = 0; # We have to start from scratch if we optimise here
            # ...maybe not I think we only need to go back $i -9 for the

            # optimsation to work
            redo;
    }
}

print "  [".join(",",  @results)."]\n";

**********************************************************************
Registered Office:
Marks and Spencer plc
Waterside House
35 North Wharf Road
London
W2 1NW

Registered No. 214436 in England and Wales.

Telephone (020) 7935 4422
Facsimile (020) 7487 2670

<<www.marksandspencer.com>>

Please note that electronic mail may be monitored.

This e-mail is confidential. If you received it by mistake, please let us know and then delete it from your system; you should not copy, disclose, or distribute its contents to anyone nor act in reliance on this e-mail, as this is prohibited and may be unlawful.
2005





More information about the london.pm mailing list