I post the draft OSS for a kind of auto clear of a $var
from a string.
Any help or hint is welcome. No, I don't like a OOP orientation.
#!/usr/bin/perl -w
use strict;
my $m = 110;
my $E = 1_000_000_000;
my $c; # incógnita
# The aim of this OSS is to put a list of macroeconomic equations and
expand them
# for all variables. Therefore giving a number of values to vars we
could make predictions
# or do simulations around the total block of equations.
my %eqs = (
"1" => "$E = $m*$c**2", # El objetivo es poner
varias ecuaciones y expandirlas en todas las $var
);
my @l = search ('$c');
for my $i (@l){
print clear('$c',$i), ";\n";
}
exit 1;
sub search {
my $var = shift;
my @result;
while (my ($k,$v) = each %eqs){
if ($v =~ /\Q$var/i){
push @result , $k;
}
}
return @result;
}
sub clear {
my ($var, $e) = @_;
my $eq = $eqs{$e};
my %antiop = (
"=" => "=",
"+" => "-",
"-" => "+",
"*" => "/",
"/" => "*",
"**" => "**1/",
"**1/" => "**",
"**2" => "**0.5",
);
my %prio = (
"=" => 0,
"+" => 1,
"-" => 1,
"/" => 2,
"*" => 3,
"**" => 4,
);
my ($n,$d);
my $s = qr/[\=|\*|\+|\-|\/]/;
goto MEJOR;
my @ss;
push @ss, $1 while ($d =~ /($s)/g); # list of ops, ordered left -
right
my @t2;
push @t2, $1 while ( $d =~ /\((.+)\)/g ); # list of subeq inside ()
my @t = split /$s/, $d; # list of vars # PROBLEM
@t2 and the rest of $d
my @nums;
push @nums, $1 while ($d =~ /(\d+)/g); # list of numbers
MEJOR:
# ENFOQUE MEJOR:
# 1) simplificar la ecuación por bloques en torno al operador/es
principales
$eq =~ s/\s+//g;
my @term;
my @oper;
while ( $eq =~ /(\Q$s\E)?\(?(.+)\)?/g ){
push @oper, (defined $1) ? $1 : "";
push @term, $2;
}
# 2) identificar cuál/es tienen la $var objetivo
my ($count, @lista);
for (@term){
$count++;
if ($_ =~ /\Q$var\E/){
push @lista, $count-1;
}else{
push @lista, -($count-1); # No puede ser 0 porque el término 0 o no
existe o ya está despejado
}
if ($var eq $_){ return $eq; } # No hay que hacer nada, es la ecuación
original
}
# 3) despejar los bloques en los que no está la $var objetivo
$count=-1;
my $eq2;
my $flag;
for my $i (@term){
$count++;
if ($lista[$count]==0){
$eq2 = $i;
}elsif ($lista[$count] < 0) {
if (index ("(", $i) >=0){
}else{
$eq2 .= $antiop{ $oper[abs($count)] } . $i;
}
}elsif ($lista[$count] > 0) {
if (index ("(", $i) >=0){
}else{
$eq2 = $antiop{ $oper[$count] } . $eq2;
if ($eq2 =~ s/ ^\/ / 1\/ /x){
# problema de paréntesis y ordenación futuro
$flag = 1;
}
}
}
}
($n,$d) = split "=", $eq2;
$eq2 = "$d = $n";
return $eq2;
# 4) tratar los bloques en que está la $var objetivo -> goto 3)
}
--
http://gamo.sdf-eu.org/
perl -E 'say "Beware of cocodriles at the toll.";'