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

I am having trouble running this subroutine. Unless the 4 characters are in common in the string at each position once in the string (so that $a,$c,$g,$t = 1 or greater) then it generates errors about having an uninitialized variable when it returns the values. I can't figure out a way around this, especially since the variable seems to have been initialized with a value.
sub comNucCount { my($string1, $string2) = @_; $string1 = lc $string1; $string2 = lc $string2; # we assume that the strings have the same length my($length) = length($string1); my($position); my($a,$c,$g,$t) = "0"; for ($position=0; $position < $length ; ++$position) { if(substr($string1,$position,1) eq substr($string2,$position,1 +)) { if(substr($string1,$position,1) eq 'a'){$a++} if(substr($string1,$position,1) eq 'c'){$c++} if(substr($string1,$position,1) eq 'g'){$g++} if(substr($string1,$position,1) eq 't'){$t++} } } return "A=$a, C=$c, G=$g, T=$t"; }

Replies are listed 'Best First'.
Re: String/Integer Concatenation
by Ovid (Cardinal) on Mar 02, 2006 at 21:02 UTC

    Without really checking your code in detail, it looks like you want this:

    my($a,$c,$g,$t) = (0, 0, 0, 0); # or my($a,$c,$g,$t) = (0) x 4;

    Your version:

    my($a,$c,$g,$t) = "0";

    That initializes $a to "0" and doesn't assign any value to the other variables.

    Cheers,
    Ovid

    New address of my CGI Course.

Re: String/Integer Concatenation
by ikegami (Patriarch) on Mar 02, 2006 at 21:09 UTC

    The error occur because you're are only initializting $a. Try:

    my ($a,$c,$g,$t) = (0, 0, 0, 0);

    or

    my $a = 0; my $c = 0; my $g = 0; my $t = 0;

    Notice the lack of quotes around a numerical zero.

    Aside from that,

    • you have lots of redundancy,
    • you use the less readable form of for,
    • you use $a which is special, and
    • you use four seperate vars ($a,$c,$g,$t) where a hash would be better.

    Fix:

    sub comNucCount { my($string1, $string2) = @_; $string1 = uc $string1; $string2 = uc $string2; my %counts = map { $_ => 0 } qw( A C G T ); for my $position (0 .. length($string1)-1) { my $char = substr($string1,$position,1); $counts{$char}++ if substr($string2, $position, 1) eq $char; } return "A=$counts{A}, C=$counts{C}, G=$counts{G}, T=$counts{T}"; }
Re: String/Integer Concatenation
by GrandFather (Saint) on Mar 02, 2006 at 21:53 UTC

    Another way to do it - avoid all that fiddly substr stuff:

    use strict; use warnings; print comNucCount('acgtacgtacgtacgt', 'aaaaccccggggtttt'), "\n"; sub comNucCount { my @str1 = split '', lc shift; my @str2 = split '', lc shift; my %counts = (a => 0, c => 0, g => 0, t => 0); for (@str1) { last if ! @str2; # Length mismatch - done $counts{$_}++ if $_ eq shift @str2; } return "A=$counts{'a'}, C=$counts{'c'}, G=$counts{'g'}, T=$counts{ +'t'}"; }

    Prints:

    A=1, C=1, G=1, T=1

    DWIM is Perl's answer to Gödel