use v5.36;
use strict;
-my %names;
-my %vals;
+my %expr;
+my %val;
while (<>) {
chomp;
- my ($name, $rest) = split /:/;
- $names{$name} = $rest;
- $vals{$name} = 0+$rest if $rest =~ /\A\s*\d+\z/;
+ my ($name, $rest) = split /: /;
+ my @ops = split /\s+/, $rest;
+ if (@ops > 1) {
+ $expr{$name} = \@ops;
+ } else {
+ $val{$name} = $ops[0];
+ }
}
-while (!defined $vals{root}) {
- for my $n (keys %names) {
- next if defined $vals{$n};
- my $e = $names{$n};
- my $d = 1;
- for my $v (keys %vals) {
- $e =~ s/$v/$vals{$v}/g;
- }
- next if $e =~ /[a-z]/;
- say "eval $e";
- eval "\$vals{$n} = $e";
- say "set \$vals{$n} to $vals{$n}" unless $@;
+sub walk($var) {
+ return $val{$var} if defined $val{$var};
+ my ($arg1, $op, $arg2) = @{ $expr{$var} };
+ if ($op eq '+') {
+ return $val{$var} = walk($arg1) + walk($arg2);
+ } elsif ($op eq '-') {
+ return $val{$var} = walk($arg1) - walk($arg2);
+ } elsif ($op eq '*') {
+ return $val{$var} = walk($arg1) * walk($arg2);
+ } elsif ($op eq '/') {
+ return $val{$var} = walk($arg1) / walk($arg2);
}
- say " ================= ";
}
-say $vals{root};
+say walk('root');
use v5.36;
use strict;
-undef $SIG{__WARN__};
-my %names;
-my %vals;
+my %expr;
+my %val;
while (<>) {
chomp;
- my ($name, $rest) = split /:/;
- $names{$name} = $rest;
- $vals{$name} = 0+$rest if $rest =~ /\A\s*\d+\z/;
+ my ($name, $rest) = split /: /;
+ my @ops = split /\s+/, $rest;
+ if (@ops > 1) {
+ $expr{$name} = \@ops;
+ } else {
+ $val{$name} = $ops[0];
+ }
}
-delete $vals{humn};
-$names{humn} = 'xx';
-
-while (!defined $vals{root}) {
- my $added;
- for my $n (keys %names) {
- no warnings;
- next if defined $vals{$n};
- my $e = $names{$n};
- my $d = 1;
- for my $v (keys %vals) {
- $e =~ s/$v/$vals{$v}/g;
- $names{$n} = $e;
- }
- next if $e =~ /[a-z]/;
-
- eval "\$vals{$n} = $e";
- # say "set \$vals{$n} to $vals{$n}" unless $@;
- $added = 1;
+sub walk($var) {
+ return $val{$var} if defined $val{$var};
+ return undef if !defined $expr{$var};
+ my ($arg1, $op, $arg2) = @{ $expr{$var} };
+ my $val1 = walk($arg1);
+ my $val2 = walk($arg2);
+ return undef if !defined $val1 || !defined $val2;
+ if ($op eq '+') {
+ return $val{$var} = $val1 + $val2;
+ } elsif ($op eq '-') {
+ return $val{$var} = $val1 - $val2;
+ } elsif ($op eq '*') {
+ return $val{$var} = $val1 * $val2;
+ } elsif ($op eq '/') {
+ return $val{$var} = $val1 / $val2;
}
- last if !$added;
}
-for my $n (sort keys %names) {
- say "$n = ", defined $vals{$n} ? $vals{$n} : $names{$n};
-}
-my ($val) = $names{root} =~ /(\d+)/;
-my ($var) = $names{root} =~ /([a-z]+)/;
-while (defined $var) {
- say "$var = $val, var = $names{$var}";
- my ($arg1, $op, $arg2) = $names{$var} =~ /(\w+)\s+(\S)\s+(\w+)/;
- say "-> $arg1 $op $arg2";
+delete $val{humn};
+delete $expr{humn};
+walk('root');
+my $val = $val{$expr{root}[2]};
+my $var = $expr{root}[0];
+
+while ($var ne 'humn') {
+ say "$var = $val, expr = @{ $expr{$var} }";
+ my ($arg1, $op, $arg2) = @{ $expr{$var} };
+ $arg1 = $val{$arg1} if defined $val{$arg1};
+ $arg2 = $val{$arg2} if defined $val{$arg2};
if ($arg2 =~ /\d/) {
$var = $arg1;
if ($op eq '/') {
} elsif ($op eq '-') {
$val = $val + $arg2;
}
- say "var $var = $val";
} elsif ($arg1 =~ /\d/) {
$var = $arg2;
if ($op eq '/') {
} elsif ($op eq '-') {
$val = $arg1 - $val;
}
- say "var $var = $val";
- if ($var eq 'humn') {
- $vals{humn} = $val;
- last;
- }
} else {
last;
}
+ say "var $var = $val";
+ $val{$var} = $val;
}
-say $vals{humn};
+
+say $val{humn};