Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister

string functions

by valavanp (Curate)
on Oct 25, 2006 at 08:34 UTC ( #580509=perlquestion: print w/replies, xml ) Need Help??
valavanp has asked for the wisdom of the Perl Monks concerning the following question:

I have a string. $a="2A2B2C". The values of A,B,C are stored in an array @p=(1.5,2.5,3.5). The result of $a should be like this: (AA)*(50/100) (BB)*(55/100) (CC)*(60/100). The values of A,B,C should be repeated according to the adjacent number before that character. I may be wrong somewhere in the coding. The answer should be 28.4238 where as i am getting 2.165625. Here is the code which i used:
$a="2A2B2C"; @p=(1.5,2.5,3.5); #print substr($a,0,1); #print "\n"; $b=length($a); print "$b\n"; for($i=0;$i<$b;$i++){ $a=~s/(\d+)(.)/$2 x $1/ge; } #print $a; for(1..$b) { if(1==$_) { $c=substr($a,0,1); $r1=$p[0]*(50/100); print $r1; } elsif(2==$_) { $c2=substr($a,1,1); #print "\n$c"; } elsif(3==$_) { $c3=substr($a,2,1); $r2=$p[1]*(55/100); print "\n$r2"; } elsif(4==$_) { $c4=substr($a,3,1); #print "\n$c"; } elsif(5==$_) { $c5=substr($a,3,1); $r3=$p[2]*(60/100); #print "\n$r3"; } elsif(6==$_) { $c6=substr($a,5,1); #print "\n$c"; } } $answer=$r1*$r2*$r3; print "\n$answer";

Replies are listed 'Best First'.
Re: string functions
by Corion (Pope) on Oct 25, 2006 at 08:54 UTC

    There are many errors or weird things in your program

    1. You are not indenting your code properly so it is very hard to see what loop goes around what code.
    2. Your string expansion is very weird. Why do you expand your string 2A2B2C in a loop when the regular expression already does the complete expansion?
    3. Your string length calculation is wrong. You calculate the length of the unexpanded string 2A2B2C instead of calculating the length of the expanded string. Also, name your length variable something better than $b. Maybe call it $string_length or $sequence_length, so that you and others understand what you are doing.
    4. Your if ... elsif ... structure is very, very bad and error prone. If you want to associate a letter with a value, a hash is the natural structure:
      my %value = ( A => 1.5, B => 2.5, C => 3.5, ); my %factor = ( A => 50/100, B => 55/100, C => 60/100, );

      You can then easily split up your string and calculate the numbers.

      my @letters = split //, $expanded_string; my $result = 0; for my $letter (@letters) { $result = $result + $value{ $letter } * $factor{ $letter }; }; print $result;

    With these changes, I get a result of 8.45, so either your calculation of 28.4238 is wrong or you need to explain how you arrive at that number. Basically, my code calculates the following number:

    $result = 1.5 * (50/100) * 2 + 2.5 * (55/100) * 2 + 3.5 * (60/100) * 2
      The result is the product of 2A2B2C. You have summed up like this (2A)*(50/100)+(2B) * (55/100)+(2C) * (60/100). But i need the product of the result. In the morning when i am in the chatter box tye suggested me to go for if loop, that's why i went through if else.

        If you need the product, why are you expanding your string at all? You should then be able to calculate your product by simply multiplying the letters by their factors in front. But if I interpret what you say that way, I still don't get your result:

        perl -le "print 2*1.5*(50/100)*2*2.5*(55/100)*2*3.5*(60/100)" 17.325

        Please explain what calculation you want to perform.

        The structure of if..elsif is a very cumbersome way to approach your problem, so I doubt that tye recommended it as a solution for this specific problem.

Re: string functions
by Samy_rio (Vicar) on Oct 25, 2006 at 09:32 UTC

    Hi valavanp, Try like this,

    use strict; use warnings; my $str = "2A2B2C"; my %p = (A => 1.5, B => 2.5, C => 3.5); my @arr = split/(?=\d+)/, $str; my $range = 50; map{s/^(\d+)([^\d]+)$/(($p{$2}."\*") x $1)."$range\/100"/e; $range+=5; +}@arr; $str = eval join'*', @arr; print $str;

    valavanp, see below for The range is (50,55,60,65,70,75,80,85,90). How can i code that. your solutions.

    use strict; use warnings; my $str = "2A2B2C"; my %p = (A => 1.5, B => 2.5, C => 3.5); my @arr = split/(?=\d+)/, $str; my @range = (50,55,60,65,70,75,80,85,90); my $i =0; map{s/^(\d+)([^\d]+)$/(($p{$2}."\*") x $1)."$range[$i]\/100"/e; $i++;} +@arr; $str = eval join'*', @arr; print $str;

    Velusamy R.

    eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';

      The range you have used in the code is 50 and incrementing it by +5. I have these ranges in an array in corresponding to the LETTER in %p. The range is (50,55,60,65,70,75,80,85,90). How can i code that. your solutions.
Re: string functions
by holli (Monsignor) on Oct 25, 2006 at 09:32 UTC
    The following uses regexes and eval:
    use strict; use warnings; my @p = (1.5, 2.5, 3.5 ); my @m = (0.5, 0.55, 0.60); my $a="2A2B2C"; sub calc { my $i = shift; my $j = ord(shift)-65; my $r = $p[$j]; $r *= $p[$j] for (0..$i-2); return $r * $m[$j]; } $a=~ s/([0-9]+)([A-Z])/(calc($1,"$2"))/g; $a=~ s/\)\(/)*(/g; eval "\$a = $a;"; print $a; #28.423828125

    holli, /regexed monk/
      Thanks all perl monks for your answers in this node. The answer given by holli gets me the output. But i couldn't understand the code can anyone brief that. Thanks monks.
      your solution works for 2A2B2C. But for 4AC, ABC,BC it directly prints the string. your solutions.
        Is this what you want? Sorry, but your speccs are not very clear ...
        2A2B2C = 28.423828125 4AC = 5.315625 ABC = 2.165625 BC = 2.8875

        This was produces by the following code (adapted from holiy's solution):

        use strict; use warnings; my @p = (1.5, 2.5, 3.5 ); my @m = (0.5, 0.55, 0.60); sub calc { my $i = shift || 1; my $idx = ord(shift)-65; return $m[$idx] * ($p[$idx]**$i); } for my $str (qw/2A2B2C 4AC ABC BC/) { my $res = 1; while ($str =~ /(\d)?([A-Z])/g) { $res *= calc($1, $2); } print "$str = $res\n"; }

        -- Hofmator

        Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://580509]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (11)
As of 2017-01-24 09:29 GMT
Find Nodes?
    Voting Booth?
    Do you watch meteor showers?

    Results (203 votes). Check out past polls.