DEV Community

Discussion on: Advent of Code 2020 Solution Megathread - Day 18: Operation Order

Collapse
 
choroba profile image
E. Choroba • Edited

My Perl solution. I used the Marpa::R2 library to write a parser. It supports rule precedence, so solving the part 2 took me just a minute.

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

use List::Util qw{ sum };
use Marpa::R2;

my $DSL = << '__DSL__';

:default ::= action => [name,values]
lexeme default = latm => 1

Expression ::= ('(') Expression (')')  assoc => group  action => ::first
             | digits                                  action => ::first
            || Expression op Expression                action => main::operate

whitespace ~ [\s]+
digits     ~ [\d]+
op         ~ [+*]
:discard   ~ whitespace

__DSL__

sub operate {
    {'+' => sub { $_[0] + $_[1] },
     '*' => sub { $_[0] * $_[1] }
    }->{$_[2]}->($_[1], $_[3])
}

my $grammar = 'Marpa::R2::Scanless::G'->new({source => \$DSL});
sub evaluate {
    my ($expression) = @_;
    return ${ $grammar->parse(\$expression) }
}

say sum(map evaluate($_), <>);
Enter fullscreen mode Exit fullscreen mode

For part 2, the DSL is

Expression ::= ('(') Expression (')') assoc => group action => ::first
             | digits                                action => ::first
            || Expression '+' Expression             action => main::operate
            || Expression '*' Expression             action => main::operate

whitespace ~ [\s]+
digits     ~ [\d]+
:discard   ~ whitespace
Enter fullscreen mode Exit fullscreen mode