[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [MacPerl] sorting algorithms



on 11/10/2000 01:20 AM, Ken Williams at ken@forum.swarthmore.edu wrote:

> mactech@webdragon.net (Scott R. Godin) wrote:
>> on 11/09/2000 07:05 PM, Paul McCann at pmccann@maths.adelaide.edu.au wrote:
>>> # first a reference to allow less typing in what follows.
>>> 
>>> $ref=\%{$master_maps_list{$gametype}};
>> 
>> Nice trick. I knew this existed, but really hadn't seen it in action in the
>> context of what I'm using the script for. I'll have to ponder this sort of
>> usage and see if it can help me any in the future. *thanks*
> 
> Actually, you can avoid making a hash just to take a reference to it,
> and replace the above line with:
> 
> $ref = $master_maps_list{$gametype};
> 
> 
>> sub coerce {
>> my $inrating = shift; # (this next is the 'hard' part)
>> #if the rating is -1 (not rated) simply reutrn the string "NA"
>> # this subroutine would thereafter ensure that the rating value was
>> # o rounded to the nearest .5 ( <.25 >.75 )
>> # o treated as a string for the return purpose.
>> # o prepended with a 0 if <10 (i.e. 07 02 10 05)
>> # o post-pended with .0 if rounded to an integer.
>> #   (i.e. 07.0 10.0 05.5 02.5)
>> return $coerced_rating;
>> }
> 
> All this rounding & place-figuring should probably be done with
> sprintf() and int(), so you can do the whole shebang without any
> case-checking:
> 
> sub coerce { sprintf '%04.1f', int(shift()*2+.5)/2 }
> 
> Coincidentally, if the rating is -1 then this returns '-0.5', and since
> '-' is before all the decimal digits in ASCII order, this will sort at
> the beginning as you want it.  You can convert it to 'NA' after the sort
> if you want to.
> 
> 
>> Does this make any sense, or am I just imagining things? Did I just get
>> *really* lucky to stumble across this germ of an idea and be in a state of
>> mind to handle the 'epiphany' or am I totally wacked and smokin' da wrong
>> sheiat? 
> 
> You're on the right track, go with it.  This is essentially the
> Guttman-Rosler Transform; you construct a string that you can pass to
> Perl's built-in sort() function.  Very efficient.

All of this info was immensely valuable -- thank you one and all.

the resultant short-test produces the EXACT output I wanted :D

With a few additional twists to spread the output into tables it should go
perfectly :) 

here's the resultant test script: (cuz I feel like showing off, being a
newbie and all :)

#!perl -w
use strict;
#use diagnostics -verbose;

use File::Spec 0.7;

#DAMN this is neat!
# completely irrelevant to the test, but still neat as a grape on velvet :-)
    use CGI::Carp qw(fatalsToBrowser set_message);
    BEGIN {
       sub handle_errors {
          my $msg = shift;
          print qq{<h2>aCk!</h2>};
          print qq{<p>I'm currently beta-testing some changes, so E-mail me,
<a href="mailto:fuzzbuster\@planetunreal.com">fuzzbuster</a>, about this if
it persists.</p><hr>};
          print "Got an error: $msg";
      }
      set_message(\&handle_errors);
    }
use CGI qw( :standard :html3 -no_xhtml );
    if ($CGI::VERSION < 2.66) {
        confess ("Your Website's System Administrator needs to install
CGI.pm version 2.66 or later to run this script.\n",
                 'The most recent version information and revision history
is at http://stein.cshl.org/WWW/software/CGI/index.html#new')
    };
use CGI::Pretty qw( :html3 );


#predefine some stuff
my $input_File = 
 File::Spec->catfile( File::Spec->curdir(), 'input_files', 'maps_list.txt');
my %master_maps_list = ();
my @data = ();

# coerce the rating value to a special format to aid in a sort transform
sub coerce2 { sprintf '%04.1f', int(shift()*2+.5)/2 }

open(IN, "<$input_File") || die "Can't open $input_File: $!";
    chomp( @data = <IN> );  # need those parens
close IN;

for (@data) {
    my($gametype, $filename, $title, $size, $review, $rating) = split /\t/;
# tried using $filename =~ lc($filename) here but it kept giving me errors
# due to the presence of ][ characters in the file-names
    (my $coercename = $filename) =~ tr/[A-Z]/[a-z]/;
    $master_maps_list{$gametype}{ coerce2($rating) . $coercename } =
                              [$filename, $title, $size, $review, $rating];
}

foreach my $gametype (sort keys %master_maps_list) {
    my $typeref = $master_maps_list{$gametype};
    for (reverse sort keys %{$typeref}) {
        print($_, ' -> ', join( ', ',  @{$typeref->{$_}}), "\n")
    }
}



# ===== Want to unsubscribe from this list?
# ===== Send mail with body "unsubscribe" to macperl-request@macperl.org