Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

What is wrong with this math equation? None of the examples on my last post aided in this headache :(
my $page = url_param('page'); my $top = $page* 20); my $bottom = $top - 20; if ($page ne "") { for ( grep defined($_), ( reverse keys %upload )[ $bottom .. $top ] ) +{ do this if url_param exists ... } else { for ( grep defined($_), (reverse keys %upload )[ 0 .. 19] ) { do this if on first page, without url_param ... }
First of all, the hash is ALWAYS retrieved in a specific order, so we don't need to worry about that. I'm trying to get this to print the latest 20 images inserted into the DB on the first page (or page without a url_param) and apply a mathematical equation to figure out the proper range of each extra page.

I'm trying to accomplish something like:

page 1: latest 20 entries
page 2: 20 entries older than page 1
page 3: 20 entries older than page 2
page 4: 20 entries older than page 3

But the problem is, the equation isn't quite right because on some pages (other than the main page) it prints image 1 in it's range and on the next consecutive page it starts with image 1. It's using the same image on both pages.

Can anyone offer any advice?

Replies are listed 'Best First'.
Re: mathematical equation
by sulfericacid (Deacon) on Jul 27, 2003 at 22:36 UTC
    This still seems kind of weird or hard to think about. But think about it like this.

    Page 1 shows items 0 - 19, right?
    Page 2 shows items 20 - 40 (which works fine, no duplicates)
    Page 3 would show items 40 - 60 (first duplicate (#40)
    Page 4 would show items 60 - 80 (next duplicate (#60)

    After page two your last item on the patch will duplicate the first item on the next page (in a consecutive ++). I don't know if this would work, but maybe add another <if> statement that does something like:

    my $page = url_param('page'); if ($page > 2) { my $top = $page * 20); my $bottom = $top - 19;


    "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

    sulfericacid

      See my comments at my other reply to you.

      Replace the latter half of your "galleryprint.pl" script with something like this:

      my $page = url_param('page'); $page ||= 1; my $first = ($page - 1) * 20; my $last = $first + 19; print "<table>\n"; my $counter = 0; for ( (grep defined, reverse keys %upload)[ $first .. $last ] ) { my ( $filename, $width, $height ) = split ( /::/, $upload{$_} ); print " <tr>" unless ( $counter % 5 ); print qq(<td width=120" height="120">), qq(<a href="$imagedir/$filename" target="new">), qq(<img src="$imagedir/$filename" height="100" width="100">) +, qq(</a></td>); unless ( ++$counter % 5 ) { print "</tr>\n"; } } print "</table>";
      I renamed the variables $first and $last to avoid the ambiguity of $bottom and $top I.e. It wasn't easy to tell whether you meant "bottom of page" or "bottom of range" (The bottom of the page would be the top of the range.) Whereas, $first is unambiguous because it is both the first image on the page and the first index in the range. Likewise with $last.

      -sauoq
      "My two cents aren't worth a dime.";
      
Re: mathematical equation
by fergal (Chaplain) on Jul 27, 2003 at 23:00 UTC
    First of all, the hash is ALWAYS retrieved in a specific order, so we don't need to worry about that.

    I'm worried about that. Why will it ALWAYS return in the correct order? Is it a special tied hash or something? If not, then the order may as well be random. In fact in perl5.8.1, for security reasons, the order is going to different every time you run the code.

    Anyway, one thing that strikes me is that your range is funny. If $page = 2, then $top = 40 and $bottom = 20, which will give you 21 items per page. So I think you want to do

    my $top = ($page * 20) - 1; my $bottom = $top - 19;
    and then, rather than having a special case for $page="" you could write the whole thing as
    my $page = url_param('page'); $page = 1 if $page eq ""; # fixup $page my $top = $page* 20 - 1; my $bottom = $top - 19; for ( grep defined($_), ( reverse keys %upload )[ $bottom .. $top ] ) { do this if url_param exists ... }

    That said, I don't think there's anything in the above that would fix the symptoms you've described...

Re: mathematical equation
by sauoq (Abbot) on Jul 28, 2003 at 03:54 UTC

    Assuming $top is supposed to be at the top of the page and $bottom is supposed to be at the bottom of the page and pages start at one and the first image index you want is zero, then you want:

    $top = $page * 20 - 20; $bottom = $top + 19;
    If pages and image indexes both start at zero, you want:
    $top = $page * 20; $bottom = $top + 19;
    If image indexes start at one and pages start at one, you want:
    $top = $page * 20 - 19; $bottom = $top + 19; # A clearer Alternative: $bottom = $page * 20; $top = $bottom - 19;
    If image indexes start at one and pages start at zero, you want:
    $top = $pages * 20 + 1; $bottom = $top + 19;
    This stuff really isn't that difficult. I can't imagine why everyone has had so much trouble with it.

    I assume, BTW, that you are using Tie::IxHash or something. Otherwise you absolutely cannot rely on the order of the keys.

    -sauoq
    "My two cents aren't worth a dime.";
    
      I was wondering if you could clear a few things up..

      I need different equations depending on what page I'm on, so I devised

      if ($page < 1) { for ( grep defined($_), ( reverse keys %upload )[ -19 .. 0 ] ) { } elsif ($page eq 2) { my $top = ($page * 20); my $bottom = $top - 19; } else ($page > 2) { my $top = $page * 20; my $bottom = $top - 19; }
      On the first if statement, it's printing incorrectly. It's printing images 4, 3, 2, 1, 2 instead of just 4, 3, 2, 1. It must be pulling a range that's to be used with one of the other loops, have any idea how? Because ?page=2 returns images 1, 2, 10, 9... (one of these two aren't supposed to be pulling the 1, 2 but I can't figure out which one).

      All pages=3 and up are working properly, it's just page 1 and two which are sharing the same pictures. (When I say picture numbers, it just means I uploaded test images with numbers on them so I could see which order they went in).

      I'm using something like that module you said. Any ideas on what part of the equations is wrong?

        I need different equations depending on what page I'm on, so I devised

        Well, you should test the code you "devise" before asking for help on it. It only takes a glance to see that won't even compile. You're missing a curly on your for loop and that else in else ($page > 2) would need to be an elsif. That's syntax... There's the logic error too. Even if that was an elsif you'd still be missing a case for $page == 1. You have cases for $page < 1 and $page eq 2 (which is another error, btw; it should be $page == 2). And that's ignoring the fact that your last case is exactly the same as your second one!

        And all that aside, why would you need to special case pages 1 and 2? It seems to me that you are making a simple task far too hard.

        Frankly, you aren't explaining yourself very well either and since you seem to have some command of idiomatic English, I don't think it is an ESL issue. If you can state your problem clearly and provide code that you've actually tried, I'm sure you'll be successfully helped. As things are now, you've posted essentially the same question twice, gotten a half dozen or more replies, and you seem to be no further along with your task.

        -sauoq
        "My two cents aren't worth a dime.";
        
        ( reverse keys %upload )[ -19 .. 0 ]

        That's not going to do what you think unless there are exactly 20 keys.

        my @array = 1 .. 40; print $_ for @array[-19 .. 0];

        Also, by grepping the defined elements out of your 20 element slice, you risk having less than 20 elements to work with. You probably want to grep the defined elements first and then work with the appropriate 20 element slice.

        -sauoq
        "My two cents aren't worth a dime.";
        
Re: mathematical equation
by halley (Prior) on Jul 28, 2003 at 14:06 UTC

    This series of questions by this Anonymous Monk has the uncanny sound of someone who hasn't applied much discipline in deriving a proper method. It's delved into the realm of 'voodoo programming' where special cases are added on top of previous hacks to ensure that page 3 gets the right 20 elements. No offense or anything, but when you're going in circles, it helps to reconsider the technique.

    Whenever I get flummoxed with problems involving iteration or geometry, I whip out the graph paper and stay away from the keyboard until I'm certain of the correct approach. Keyboards force you to think in terms of the symbols, which is not always the most effective way to think.

    Draw a diagram of the database's records. Draw little lines or brackets showing the region you want for a given query. If real-world parameters like '20 elements' is too cumbersome to draw in the diagram, use smaller parameters like 4 or 5. (This trick will also help you properly parameterize your solution in code later.)

    Once you're sure you've identified all the parameters, simulate the query on another sheet with a fresh diagram of the database. Be the computer. Be ruthlessly naive and follow only the steps you've properly and fully explained. If you can't empathize with your student, you can't teach the student.

    Then you're ready to type in the pseudocode in English. Write your pseudocode as a series of comments. In plain English. With little text versions of your diagrams if that helps. In just plain English without variable names at all. Explain what you want done before you make the computer do it. Did I mention you should write in plain English? Strategy in comments.

    Finally, translate the pseudocode into real code underneath each sentence. Explain in computer language exactly how they should accomplish the goal. Use the parameters you've identified, and use the steps that will work. Tactics in code.

    The proper code will have an obvious reason for each statement and variable, and you won't need special cases or hacks or adjustments for any weird artifacts that aren't a crucial part of your problem definition. Someone else has a .sig which reads something like "I know I'm on the right track when I'm deleting code in order to provide more functionality."

    --
    [ e d @ h a l l e y . c c ]