Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options

Issue with grep & getting the right hash values out & possibly some other stuff

by crunch_this! (Acolyte)
on Apr 08, 2013 at 18:24 UTC ( #1027571=perlquestion: print w/replies, xml ) Need Help??
crunch_this! has asked for the wisdom of the Perl Monks concerning the following question:

First question here... I'm interested in creating all the polynomials, their derivatives & sets of zeros of the derivatives, & keeping them all together. So a hash of hashes seems appropriate to me (if anyone has a better idea I'm all ears). I've managed to print out all of those things using nested for loops (to see if it would work) but putting them into a hash is what's giving me trouble. Using bits that I found on this site & Programming Perl I also found that the only key is 6 (just the number 6). A complicating factor is that I'm also only interested in cases where a, b & c are all different. So issues here that I can see:
1. definitely my hash definition
2. possibly the if loop
3. possibly using foreach loops
I've tried other things, like a while loop, putting the if on the "outside", etc but haven't had much luck with anything else, not the way I did it anyway.

Here's the relevant stuff that I've done so far:

use Math::Polynomial::Solve qw!poly_derivative poly_roots!; my %haystack; my $rep = int 5; # $rep means right endpoint of the interval [0, $rep] foreach ( $a = 1; $a <= $rep; $a++ ) { foreach ( $b = 1; $b <= $rep; $b++ ) { foreach ( $c = 1; $c <= $rep; $c++ ) { if ( $a == $b || $b == $c || $c == $a ){ next; } else { # expanded form of (x^2)*(x - a)*(x - b)*(x - c) # coeffs are in an array my @quintic = (1, -$a - $b - $c, $a*$b + $a*$c + $b*$c +, -$a*$b*$c, 0, 0); my @derivative = poly_derivative(@quintic); my @zeros = poly_roots(@derivative); $haystack{@quintic}{@derivative} = @zeros; } } } }
UPDATE: Like I said in the comment below, I've gone with an ordinry hash, so I've changed hdb's code a bit to simply say
$haystack{"$a, $b, $c"} =  \@zeros;
Seems to work ok. Now I want to search the values, so I reversed the hash because I read that searching the keys is optimized in perl. But I still have a tricky problem because the new keys aren't strings, but arrays. I've also been reading up on grep for how to pick out the (new) values that I'm interested in. I read that in perl it's supposed to be more efficient to search the keys rather than the values. so I reversed the hash but the problem with that is that instead of just strings, I have arrays of strings. Here's what I've come up with. It compiles ok but I'm not 100% sure it does what I want it to:
# the arrays of zeros are now the keys %haystack = reverse %haystack; # supposed to search the keys for zero sets that only contain numbers +within 0.0001 of an integer my @wants = grep { / (.*\.0000.*)|(.*\.9999.*) / } keys %haystack; # supposed to print out the corresponding values from %haystack print Dumper{ values of a, b, c corresponding to the elements of @want +s };
Part of the problem is I don't think I know how to make sure that grep will look for the zero sets whose elements ALL have the form indicated, or that it will look for solution sets that just have at least one (which would be all of them in this case & not very interesting). Something else that caught my eye at the bottom of the Dumper manpage is a subroutine that filters keys out of a hash; I wonder if that could be adapted here because that module is really cool.

Replies are listed 'Best First'.
Re: Issue with hash definition & possibly some other stuff
by BrowserUk (Pope) on Apr 08, 2013 at 18:44 UTC
    I also found that the only key is 6 (just the number 6).

    The problem is that you are using the size of the arrays (eg. @quintic in a scalar context) as your hash keys. If you quoted the hashes thus:

    $haystack{ "@quintic" }{ "@derivative" } = \@zeros;

    Or used join something like this:

    $haystack{ join ',', @quintic }{ join ',', @derivative } = \@zeros;

    That might be nearer to what you are after, though it may not sure all the ills.

    Note also that I've backslashed \@zeros to store a reference to the array, otherwise you are again storing the size of the array, not its contents.

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Issue with hash definition & possibly some other stuff
by hdb (Prior) on Apr 08, 2013 at 21:27 UTC

    A few comments:

    • The symmetry of the problem leads to 10 different cases only. We can assume that 1<=$c<$b<$a<=$rep.
    • This also implies that $a is always at least 3, and $b at least 2.
    • This way the loops are simpler and no check for equality is required.
    • I think that $a, $b, $c are the correct parameters to store the results rather than the polynomials itself.
    Here is my proposed code:

    use strict; use warnings; use Math::Polynomial::Solve qw!poly_derivative poly_roots!; use Data::Dumper; my %haystack; my $rep = int 5; # $rep means right endpoint of the interval [0, $rep] foreach my $a (3..$rep ) { foreach my $b (2..$a-1 ) { foreach my $c (1..$b-1 ) { my @quintic = (1, -$a - $b - $c, $a*$b + $a*$c + $b*$c, -$a*$b*$ +c, 0, 0); my @derivative = poly_derivative(@quintic); my @zeros = poly_roots(@derivative); $haystack{"$a,$b,$c"}{"p"} = \@quintic; $haystack{"$a,$b,$c"}{"d"} = \@derivative; $haystack{"$a,$b,$c"}{"z"} = \@zeros; } } } print Dumper{%haystack};
      That makes a lot of sense when I think of what the problem is, especially the first & last things. Once I got it working I confirmed what I suspected that I actually don't really need to know what the derivatives actually are, only what their zeros are. So I actually only need an ordinary hash. Now that I've got the hash part fixed I want to search the values for zero sets that only contain integers, or maybe values within 0.0001 of an integer since the Solve module uses a numerical matrix method to find the zeros, then print out its key. I think grep is what I'm looking for. Thx for all the help so far everybody :D
      btw that dumper module is a real lifesaver!
Re: Issue with hash definition & possibly some other stuff
by sundialsvc4 (Abbot) on Apr 08, 2013 at 21:39 UTC

    Echoing BrowserUK ... “the key,” in any hashref, must be “a string.” What you are using right now will be coerced by Perl into “a string,” but it won’t be a string that you can use in this case.   Therefore, you need to produce, from the arrays that you have, some kind of “single string,”   and to make sure that it’s the string that you want.   When developing code like this, I usually add a few extra statements ... creating a few extra scalar variables (my $d= ...; my $z= ...), inserting some statement (such as the suggested join() to produce the value, then perhaps initially adding print STDERR "d=$d, z=$z\n"; so that I can see what value Perl actually came up with (undoubtedly contrary to my expectations).   Once I’m satisfied with the two strings, I use them in a statement like $$haystack{$d}{$z} = \@zeroes;

    The “extra” dollar-sign is functionally equivalent to $haystack->{$d}{$z} ... it’s up to you.

    The backslash to the right of the equals-sign is also important:   a hashref is always a collection, indexed by “a string,” to “a scalar,” which in this case should be a reference to an array.   (Look up “references” here.)

    Also, in all code, be sure to use: use strict; use warnings;.   Perl is designed to be very accepting and forgiving ... it will try to do what you ask, according to its own interpretation.   These two pragmas will tell it to alert you to mistakes that you probably didn’t realize you were making.   Your code should “run clean,” with no errors or warnings raised.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1027571]
Approved by marto
[1nickt]: the tick that can make you a vegetarian
[perldigious]: Your Mother: Yeah, I have a tool for ticks that I use (mostly on my dogs thankfully), but it's just a cheapo one I got from my vets office... it works pretty good though.
erix saw a tick in a natural history museum collected from the scrotum of the curator (it was removed)
[Your Mother]: The exhibit, the tick, or the scrotum?
[erix]: (the man is even a paleontologist )
[1nickt]: erix unfortunately that's there favourite spot. That's why they are usually spotted crawling *up* your leg.
[erix]: ha, the tick and, as it happens, also the curator (now a professor of Paleont.)
[1nickt]: s/there/their/, ugh sorry.
[Your Mother]: Heh. The only one I ever had on me, I caught on my shin, headed north.
erix looks nervously I got away cleanly from my run , it seems :)

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (15)
As of 2017-05-24 13:16 GMT
Find Nodes?
    Voting Booth?