#! /perl/bin/perl # # Created Jan 11, 2001 Scott Oglesby # http://www.kurumi.com/roads/route.txt # # Modified: # Mar 29, 2001 Added missing Baltimore SMSA to I-95 # May 31, 2004 Corrected length of I-4 thanks to Rmsuperstar99@aol.com # # "Objectively" rank 1- and 2-digit interstate highways. # Good for starting all sorts of arguments. # # Toward the end of the file are switchable parameters # give different weighting to (or ignore entirely) certain criteria # # Conventions: # - '84e' means the eastern I-84, considered separate from '84w'. # important/major 2dis. It's "worth more" to intersect one of these. @big2dis = qw(5 10 15 20 25 35 40 55 65 75 80 81 85 90 94 95); # list of states a 2di traverses. # Only used for counting # of states passed; the particular names are ignored. %states = ( '4' => 'fl', '5' => 'ca or wa', '8' => 'ca az', '10' => 'ca az nm tx la al ms fl', '12' => 'la', '15' => 'ca az nv ut mt', '16' => 'ga', '17' => 'az', '19' => 'az', '20' => 'tx la ms al ga sc', '24' => 'il ky tn ga', '25' => 'nm co wy', '26' => 'sc nc', '27' => 'tx', '29' => 'mo ia sd nd', '30' => 'tx ar', '35' => 'tx ok ks mo ia mn', '37' => 'tx', '39' => 'il wi', '40' => 'ca az nm tx ok ar tn nc', '43' => 'wi', '44' => 'tx ok mo', '45' => 'tx', '49' => 'la', '55' => 'la ms tn ar mo il', '57' => 'mo il', '59' => 'la ms al ga', '64' => 'mo il in ky wv va', '65' => 'al tn ky in', '66' => 'va', '68' => 'wv md', '69' => 'in mi', '70' => 'co ks mo il in oh pa md', '71' => 'oh ky', '72' => 'il', '74' => 'ia il in oh', '75' => 'fl ga tn ky oh mi', '76w' => 'co ne', '76e' => 'oh pa nj', '77' => 'oh wv va nc sc', '78' => 'pa nj', '79' => 'pa wv', '80' => 'ca nv ut wy ne ia il in oh pa nj ny', '81' => 'tn va wv md pa ny', '82' => 'wa or', '83' => 'pa md', '84w' => 'or id ut', '84e' => 'pa ny ct ma', '85' => 'al ga sc nc va', '86w' => 'id', '86e' => 'pa ny', '87' => 'ny', '88w' => 'il', '88e' => 'ny', '89' => 'nh vt', '90' => 'wa id mt nd mn wi il in oh pa na ma', '91' => 'ct ma vt', '93' => 'ma nh vt', '94' => 'mt nd mn wi il in mi', '95' => 'fl ga sc nc va md de pa nj ny ct ma ri nh me', '96' => 'mi', '97' => 'md', '99' => 'pa', ); # list of international borders a 2di reaches. # "cn" = canada; "mx" = mexico # hwys without border crossings can be safely omitted from list %intlborders = ( '5' => 'mx cn', '15' => 'cn', '19' => 'mx', '29' => 'cn', '35' => 'mx cn', '75' => 'cn', '81' => 'cn', '87' => 'cn', '89' => 'cn', '91' => 'cn', '94' => 'cn', '95' => 'cn' ); # list of metro areas the 3di serves # this is the fuzziest area and up to the most contention # use two single quotes ('') for an empty list %cities = ( '4' => 'tam orl', '5' => 'sd la sac sea', '8' => 'sd', '10' => 'la pho sa hou no jax', '12' => '', '15' => 'sd la lv slc', '16' => '', '17' => 'pho', '19' => '', '20' => 'dal atl', '24' => 'nas', '25' => 'den', '26' => '', '27' => '', '29' => 'kc', '30' => 'dal', '35' => 'sa dal okl kc min', '37' => 'hou', '39' => '', '40' => 'okl mem nas ral', '43' => 'mil', '44' => 'okl stl', '45' => 'dal hou', '49' => '', '55' => 'mem stl chi', '57' => 'chi', '59' => '', '64' => 'stl lou nor', '65' => 'nas lou ind chi', '66' => 'dc', '68' => '', '69' => 'ind', '70' => 'den kc stl ind col bal', '71' => 'lou cin col cle', '72' => '', '74' => 'ind cin', '75' => 'mia tam atl cin det', '76w' => 'den', '76e' => 'pit phi', '77' => 'cha cle', '78' => 'nyc', '79' => 'pit', '80' => 'sf sac slc chi cle nyc', '81' => '', '82' => '', '83' => 'bal', '84w' => 'por', '84e' => 'har', '85' => 'atl cha ral', '86w' => '', '86e' => '', '87' => 'nyc', '88w' => 'chi', '88e' => '', '89' => '', '90' => 'sea chi cle roc bos', '91' => 'har', '93' => 'bos', '94' => 'min mil chi det', '95' => 'mia wpb jax dc bal phi nyc pro bos', '96' => 'gra det', '97' => 'bal', ); # 2dis intersecting the route # If the 2di ends at this route (which can be worth more), # prefix the ending route with 'g' %x2dis = ( '4' => '75 95', '5' => 'g15 8 10 80 g84w g90', '8' => '5 15 10', '10' => '5 15 g17 g8 g19 g25 g20 35 37 45 g49 g12 g55 g59 g65 75 95', '12' => '10 55 59', '15' => '5 8 10 g40 g70 84w g86w 80 90', '16' => '75 95', '17' => '40 10', '19' => '10', '20' => '10 35 g30 45 49 55 59 65 75 85 26 77 95', '24' => '57 40 65 g59 75', '25' => '10 40 70 76w 80 90', '26' => '40 85 g77 20 95', '27' => '40', '29' => '70 35 80 90 94', '30' => '20 35 g45 40', '35' => '10 g37 20 30 45 40 44 70 g29 80 90 94', '37' => '10 35', '39' => '55 74 80 88w 90 94', '40' => '15 g17 25 g27 35 44 g30 55 24 65 75 g81 g26 77 85 95', '43' => '90 94', '44' => '35 40 55 64 70', '45' => '20 30 35 10', '49' => '10 20', '55' => '10 12 20 40 g57 64 g44 g39 72 74 70 80 90 94', '57' => '55 g24 64 70 g72 74 80 90 94', '59' => '10 12 20 65 24', '64' => '55 44 70 57 65 g71 75 77 81 95', '65' => '10 g85 20 59 24 40 64 71 74 g69 70 80 90 94', '66' => '81 95', '68' => '79 70', '69' => '70 74 65 80 90 94 96 75', '70' => '15 g76w 25 35 29 55 44 64 57 65 74 g69 75 71 77 79 76e g68 81 83 95', '71' => '64 65 g76e 74 75 70 77 80 90', '72' => '55 57', '74' => '80 55 g39 57 65 69 70 71 75', '75' => '95 4 10 16 20 85 24 40 64 71 70 g74 80 90 94 96 69', '76w' => '70 25 80', '76e' => '71 77 80 79 70 99 81 83 95', '77' => '80 90 71 76e 70 g79 64 81 40 85 20 26', '78' => '81 95', '79' => '90 80 76e 70 g68 77', '80' => '5 15 g84w 25 g76w 29 35 g74 g88w 90 94 55 57 39 65 69 75 71 77 76e 79 81 95', '81' => '40 77 64 g66 70 g83 76e g78 80 g84e g86e g88e 90', '82' => '90 84w', '83' => '76e 81 70 95', '84w' => '5 g82 g86w 15 80', '84e' => '81 87 91 90', '85' => '65 20 75 26 77 40 95', '86w' => '84w 15', '86e' => '90 81', '87' => '95 84e 90', '88w' => '80 39', '88e' => '81 90', '89' => '93 91', '90' => '5 g82 15 g25 29 35 g94 g39 g43 80 55 57 g65 69 75 71 77 79 g86e 81 g88e 87 91 g84e 93 95', '91' => '95 84e 90 89 g93', '93' => '95 90 g89 91', '94' => '90 29 35 39 43 55 57 80 65 75 69 96', '95' => '75 g4 g10 16 26 g20 40 g85 64 66 70 83 76e 78 g80 87 g91 90 g93', '96' => '94 75 69', '97' => '', '99' => '76e', ); # 3-digit interstates belonging to this 2di # Abbreviated list format, e.g "12" for 105 means I-105 and I-205 # include a 1st digit for all 3di's, even if there are several of # the same number (e.g. I-295) # I've listed them in order w->e and s->n %own3dis = ( '4' => '', '5' => '81462354274', '8' => '', '10' => '1721462135611', '12' => '', '15' => '22513', '16' => '5', '17' => '', '19' => '', '20' => '825', '24' => '1', '25' => '2', '26' => '15', '27' => '', '29' => '212', '30' => '456', '35' => '621234625', '37' => '', '39' => '', '40' => '2542481624', '43' => '', '44' => '24', '45' => '3', '49' => '', '55' => '123', '57' => '', '59' => '347', '64' => '12246', '65' => '154', '66' => '', '68' => '', '69' => '4', '70' => '2461226423', '71' => '24', '72' => '1', '74' => '4', '75' => '13246522642346', '76w' => '', '76e' => '31246', '77' => '22', '78' => '246', '79' => '25', '80' => '23567895114632124132', '81' => '1354', '82' => '1', '83' => '2', '84w' => '1', '84e' => '63', '85' => '1291354', '86w' => '', '86e' => '', '87' => '257', '88w' => '', '88e' => '', '89' => '1', '90' => '121412934567812', '91' => '6223', '93' => '23', '94' => '14367821', '95' => '135234613678241246831241243', '96' => '1246', '97' => '', ); # length of the 2di # grabbed these from zzyzx's site, http://www.ihoz.com %miles = ( '4' => 132, '5' => 1382, '8' => 345, '10' => 2460, '12' => 85, '15' => 1436, '16' => 169, '17' => 146, '19' => 63, '20' => 1508, '24' => 318, '25' => 1059, '26' => 261, '27' => 124, '29' => 753, '30' => 364, '35' => 1831, '37' => 142, '39' => 349, '40' => 2554, '43' => 192, '44' => 645, '45' => 284, '49' => 206, '55' => 944, '57' => 381, '59' => 442, '64' => 945, '65' => 888, '66' => 76, '68' => 114, '69' => 360, '70' => 2175, '71' => 343, '72' => 182, '74' => 414, '75' => 1787, '76w' => 185, '76e' => 443, '77' => 611, '78' => 144, '79' => 339, '80' => 2907, '81' => 824, '82' => 143, '83' => 85, '84w' => 771, '84e' => 243, '85' => 664, '86w' => 63, '86e' => 200, '87' => 346, '88w' => 143, '88e' => 131, '89' => 188, '90' => 3085, '91' => 290, '93' => 210, '94' => 1614, '95' => 1893, '96' => 192, '97' => 18, '99' => 58, ); # ------------------------------------------- # interesting settable parameters start here # Each mile of length is worth one point. # Other attributes are "worth" that many miles. # # Highway's importance is sum of all its points # # "generates" means another 2di ends at it, # e.g. I-90 generates I-25, because I-25 ends at I-90 # # An intersecting 2di can fall into only one of the # generates/intersects, major/minor categories. my $stateVal = 200; # each state the 2di resides in my $intlborderVal = 100; # each international border the 2di reaches my $genBig2diVal = 200; # each major 2di that ends at it my $gen2diVal = 100; # each minor 2di that ends at it my $xBig2diVal = 100; # each major 2di it intersects (except gen) my $x2diVal = 50; # each minor 2di it intersects (except gen) my $own3diVal = 150; # each 3di it's a parent of my $x3diVal = 50; # each other 3di it intersects (not currently used) my $megaPeepVal = 100; # for each million people in major cities # set these switches to zero to ignore that criteria # I'd use cmd line args, but cmd line processing is problematic on NT my ($useStates) = 1; # use number of states traversed my ($useIntlborders) = 1; # use number of international borders reached my ($useLength) = 1; # use its mileage my ($use2dis) = 1; # count intersecting 2dis my ($use3dis) = 1; # count owned 3dis my ($useCities) = 1; # count major cities my ($exclude99) = 1; # exclude interstate 99 # ---- don't mess with anything below here ------------- my ($numErrors) = 0; # set up 2di table foreach (@big2dis) { $big2dis{$_}++; } # set up population table while () { last if /::end/; if (/^(\w+)\s+.+?(\d+)/) { $megapeep{$1} = $2; } } # sanity check: are all metro area abbrevs recognized? foreach (keys %cities) { @citylist = split (' ', $cities{$_}); foreach $cit (@citylist) { unless ($megapeep{$cit}) { print "Error: no population value for '$cit' for I-$_\n"; $numErrors++; } } } # sanity check: consistent set of 2di intersections? # each one should show up twice, as A-B and B-A %junctions = (); foreach (keys %x2dis) { next if ($_ eq '99' and $exclude99); @m2dis = split (' ', $x2dis{$_}); foreach $rte (@m2dis) { next if ($rte eq '99' and $exclude99); # remove any 'g' for generated routes $rte =~ s/g//g; # build a string recording the intersection, # route #s sorted alphabetically # e.g. so both 5 to 10 and 10 to 5 are recorded as 10-5 $entry = join '-', sort ($_, $rte); $junctions{$entry}++; # each entry should see this twice } } foreach (keys %junctions) { if ($junctions{$_} != 2) { print "Inconsistent 2di-2di junction: $_\n"; $numErrors++; } } # tally states if ($useStates) { foreach (keys %states) { $results{$_} += $stateVal * split (' ', $states{$_}); } } # tally intl borders if ($useIntlborders) { foreach (keys %intlborders) { $results{$_} += $intlborderVal * split (' ', $intlborders{$_}); } } #tally cities if ($useCities) { foreach (keys %cities) { @citylist = split (' ', $cities{$_}); foreach $cit (@citylist) { $results{$_} += ($megaPeepVal * $megapeep{$cit}); } } } #tally miles if ($useLength) { foreach (keys %miles) { $results{$_} += $miles{$_}; } } # tally 2dis if ($use2dis) { foreach (keys %x2dis) { @m2dis = split (' ', $x2dis{$_}); foreach $rte (@m2dis) { next if ($rte eq '99' and $exclude99); # generated routes prefixed with 'g' if ($rte =~ /^g/) { $rte =~ tr/g//; # remove the g if ($big2dis{$rte}) { $results{$_} += $genBig2diVal; } else { $results{$_} += $gen2diVal; } } if ($big2dis{$rte}) { $results{$_} += $xBig2diVal; } else { $results{$_} += $x2diVal; } } } } # tally 3dis if ($use3dis) { foreach (keys %own3dis) { $results{$_} += ($own3diVal * length $own3dis{$_}); } } # compare function to rank 2di's by score. # Unfortunately, the route number itself is the tiebreaker sub betterScore { $results{$b} <=> $results{$a} || $a <=> $b; } # output print "Kurumi's Interstate Ranker\n\n"; print "Scoring:\n"; print "Each mile in length: 1\n" if $useLength; print "Each state occupied: $stateVal\n" if $useStates; print "Each international border touched: $intlborderVal\n" if $useIntlborders; print "Each major 2di generated: $genBig2diVal\n" if $use2dis; print "Each minor 2di generated: $gen2diVal\n" if $use2dis; print "Each major 2di intersected: $xBig2diVal\n" if $use2dis; print "Each minor 2di intersected: $x2diVal\n" if $use2dis; print "Each 3di it's a parent of: $own3diVal\n" if $use3dis; print "Each 1,000,000 pop in metro areas served: $megaPeepVal\n" if $useCities; print "Include I-99: ", ("yes", "no")[$exclude99], "\n"; print "\n"; $rank = 1; delete $results{'99'} if $exclude99; foreach (sort betterScore keys %results) { print "$rank. I-$_: $results{$_}\n"; $rank++; } if ($numErrors) { print "\nUnfortunately, there were some errors ($numErrors); see above.\n"; print "You can fix the errors, or do a manual recount :=)\n"; } exit; # approximately how many million people in each metro area # use the abbreviation to link metro area with an interstate __DATA__ atl Atlanta -> 3 aus Austin -> 1 bal Baltimore -> 2 bos Boston -> 3 buf Buffalo -> 1 cha Charlotte -> 1 chi Chicago -> 8 cin Cincinnati -> 1 cle Cleveland -> 2 col Columbus -> 1 dal Dallas-Fort Worth -> 4 den Denver -> 2 det Detroit -> 4 gra Grand Rapids -> 1 har Hartford -> 1 hou Houston -> 4 ind Indianapolis -> 1 jax Jacksonville -> 1 kc Kansas City -> 1 lv Las Vegas -> 1 la Los Angeles -> 16 lou Louisville -> 1 mem Memphis -> 1 mia Miami-Fort Lauderdale -> 3 mil Milwaukee -> 1 min Minneapolis-St. Paul -> 2 nas Nashville -> 1 no New Orleans -> 1 nyc New York -> 17 nor Norfolk -> 1 okl Oklahoma City -> 1 orl Orlando -> 1 phi Philadelphia -> 4 pho Phoenix -> 3 pit Pittsburgh -> 2 por Portland -> 2 pro Providence -> 1 ral Raleigh-Durham-Chapel Hill -> 1 roc Rochester -> 1 sac Sacramento -> 1 stl St. Louis -> 2 slc Salt Lake City -> 2 sa San Antonio -> 1 sd San Diego -> 2 sf San Francisco-Oakland-San Jose -> 6 sea Seattle -> 3 tam Tampa -> 2 dc Washington -> 4 wpb West Palm Beach -> 1 ::end