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";
Re: string functions by Corion (Pope) on Oct 25, 2006 at 08:54 UTC |
There are many errors or weird things in your program
-
You are not indenting your code properly so it is very hard to see what loop goes around what code.
- 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?
- 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.
- 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
| [reply] [d/l] [select] |
|
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.
| [reply] |
|
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. | [reply] [d/l] [select] |
|
Re: string functions by Samy_rio (Vicar) on Oct 25, 2006 at 09:32 UTC |
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;
Updated 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;
Regards, Velusamy R. eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';
| [reply] [d/l] [select] |
|
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.
| [reply] |
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
| [reply] [d/l] |
|
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.
| [reply] |
|
your solution works for 2A2B2C. But for 4AC, ABC,BC it directly prints the string. your solutions.
| [reply] |
|
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.
| [reply] [d/l] [select] |
|
|
|
|