]> www.fi.muni.cz Git - aoc.git/commitdiff
Day 21: slightly polished solution
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Wed, 21 Dec 2022 07:44:31 +0000 (08:44 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Wed, 21 Dec 2022 07:44:31 +0000 (08:44 +0100)
2022/41.pl
2022/42.pl

index 0603f026de29135025ddacc9a95e09e1d0bbab09..3ed9afefb7dca3b8f9f6018a9b8be418b5739c51 100755 (executable)
@@ -3,29 +3,31 @@
 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');
index 36114054c178114c1ed89fdfccd0a75141d41d29..d5edd98977dc0c2d57afb4441642a9477bc247f5 100755 (executable)
@@ -3,49 +3,49 @@
 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 '/') {
@@ -57,7 +57,6 @@ while (defined $var) {
                } elsif ($op eq '-') {
                        $val = $val + $arg2;
                }
-               say "var $var = $val";
        } elsif ($arg1 =~ /\d/) {
                $var = $arg2;
                if ($op eq '/') {
@@ -69,13 +68,11 @@ while (defined $var) {
                } 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};