recursive algorithm

 on Sep 05, 2012 at 20:57 UTC Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

i wrote a script which measure the hydrogen bond in RNA molecule, but i have this error, which i cannot handle. please help me. use of uninitialized value line 27.

```#!/usr/bin/perl
use warnings;
use strict;
my @structure;
my @bases;
my \$basestring = <STDIN>;
chomp(\$basestring);
my \$parenstring = <STDIN>;
chomp(\$parenstring);
print evalRnaStructure(\$basestring,\$parenstring)," hydrogen bonds in t
+his

structure.\n";
sub evalRnaStructure {
my (\$basestring,\$structurestring) = @_;
@bases = split(//,"5.\$basestring.3");
@structure = split(//,"(\$structurestring)");
return evalRna(0,\$#structure);
}
sub evalRna {
my (\$l,\$r) = @_;
my %bonds= (GU=>1,UG=>1,AU=>2,UA=>2,CG=>3,GC=>3);
my \$numBonds = \$bonds{\$bases[\$l].\$bases[\$r]};
my \$level = 0;
my \$ii = \$l;
for (my \$i=\$l+1; \$i<=\$r; \$i++) {
\$level--  if (\$structure[\$i] eq ")");
if (\$level==0) {
\$numBonds+= evalRna(\$ii,\$i)  if (\$structure[\$i] eq ")");
\$ii = \$i;
}
\$level++ if (\$structure[\$i] eq "(");
}
return \$numBonds;
}

Replies are listed 'Best First'.
Re: recursive algorithm
by GrandFather (Sage) on Sep 06, 2012 at 00:03 UTC

```sub evalRna {
my (\$l, \$r) = @_;
my %bonds    = (GU => 1, UG => 1, AU => 2, UA => 2, CG => 3, GC =>
+ 3);
my \$lu = "\$bases[\$l]\$bases[\$r]";
my \$numBonds = \$bonds{\$lu} || die "Bad bond type '\$lu' given \$l, \$
+r\n";

When given your sample input data you get:

```Bad bond type '5C' given 0, 21
True laziness is hard work
Re: recursive algorithm
by toolic (Bishop) on Sep 05, 2012 at 21:16 UTC
Show us what 2 values you provide on STDIN to get that warning message.

Re: recursive algorithm
by grizzley (Chaplain) on Sep 06, 2012 at 10:38 UTC
You probably think that

@bases = split(//,"5.\$basestring.3");

adds only '5' at the beginning and '3' at the end. But you are actually adding '5' and '.' at the beginning and '.' and '3' at the end. Check if your code works with

@bases = split(//,"5".\$basestring."3");

or

@bases = split(//,"5\${basestring}3");

This works without a warning

```sub evalRna {
my ( \$left, \$right ) = @_;
my %bonds    = ( GU => 1, UG => 1, AU => 2, UA => 2, CG => 3, GC =
+> 3 );
my \$numBonds = \$bonds{ \$bases[\$left] . \$bases[\$right] };
my \$level    = 0;
my \$new_left = \$left;
my \$numRna;
for ( my \$i = \$left + 1 ; \$i <= \$right ; \$i++ ) {
\$level-- if ( \$structure[\$i] eq ')' );
if ( \$level == 0 ) {
if ( \$structure[\$i] eq ')' ) {
if ( \$numRna = evalRna( \$new_left, \$i ) ) {
\$numBonds += \$numRna;
}
}
\$new_left = \$i;
}
\$level++ if ( \$structure[\$i] eq '(' );
}
return \$numBonds;
}

As you can see, I made some changes for better reading experience. The only change needed is to check if evalRna() returns undef. This caused your warnings. Maybe the return value undef is not, what your intention was.

How To Debug
by DrHyde (Prior) on Sep 06, 2012 at 10:23 UTC

What's line 27? It's hard to tell because of the line wrapping that might have happened around the text "hydrogen bonds in this structure". Also your code is unreadable because you haven't indented it, there's no comments, and your variable names aren't meaningful (having \$i and \$ii is confusing), so I'm not even going to bother trying to figure it out. So what follows is pretty generic ...

How you debug this is simple: either in the debugger or using print statements, spit out the variables on line 27 and if any of them are not what you expect, then look through your code to find where they are defined (or not defined), and so on, until you find the problem.

If you *are* expecting undef variables, then you'll want to guard any against using them inappropriately. For example, if in this line:

\$level--  if (\$structure[\$i] eq ")");

\$structure[\$i] may legitimately not be defined, then you should check for definedness before the comparison. Or if it's because \$structure[\$i] might legitimately not exist (eg if \$i is beyond the end of the array) then check for existence instead of (or as well as) definedness, to prevent auto-vivification.

If you were dealing with a hash here instead of an array, I'd just point you at Tie::Hash::Vivify - one of the "interesting ways" it can auto-vivify is by dieing with a helpful message - see this for an example. But I can't see anything on the CPAN to do similar things for arrays.

Re: recursive algorithm
by Anonymous Monk on Sep 05, 2012 at 21:22 UTC
GAGGGUCCUUUCAGUAGCAC ((...)..(((....)).))

If your structure, "((...)..(((....)).))" means tree structure like s-expression in lisp, and "." matches any gene, "GAGGGUCCUUUCAGUAGCAC" could match 11 trees.

I don't know what is "hydrogen bonds", no knowledge for genes. I hope you to describe what you are going to do, and get help of monks.

sub parse() is a little modified one from kogai dan's example(written in japanese).

regards

Create A New User
Node Status?
node history
Node Type: perlquestion [id://991941]
Approved by toolic
Front-paged by DrHyde
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (7)
As of 2018-07-16 18:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

Results (346 votes). Check out past polls.

Notices?