aboutsummaryrefslogtreecommitdiff
path: root/challenge-039/steven-wilson/perl5/ch-2.pl
blob: d7c5c5c1615f883816151e5a865fac286b149d45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#!/usr/bin/env perl
# Author: Steven Wilson
# Date: 2019-12-16
# Week: 039

# TASK #2
# Contributed by Andrezgz
# Write a script to demonstrate Reverse Polish notation(RPN). Checkout
# the wiki page for more information about RPN.
# https://en.wikipedia.org/wiki/Reverse_Polish_notation

use strict;
use warnings;
use Test::More tests => 2;

my %dt = (
    '+' => sub { $_[0] + $_[1] },
    '-' => sub { $_[0] - $_[1] },
    'x' => sub { $_[0] * $_[1] },
    '/' => sub { $_[0] / $_[1] },
);

ok( evaluate("1 2 +") == 3 );
ok( evaluate("15 7 1 1 + - / 3 x 2 1 1 + + -") == 5 );

# for each token in the postfix expression:
#   if token is an operator:
#     operand_2 ← pop from the stack
#     operand_1 ← pop from the stack
#     result ← evaluate token with operand_1 and operand_2
#     push result back onto the stack
#   else if token is an operand:
#     push token onto the stack
# result ← pop from the stack

sub evaluate {
    my $expression = shift;
    my @expression = split " ", $expression;
    my @stack      = ();
    for my $token (@expression) {
        if ( $token =~ /\d+/ ) {
            push @stack, $token;
        }
        else {
            my $operand_2 = pop @stack;
            my $operand_1 = pop @stack;
            my $result    = $dt{$token}->( $operand_1, $operand_2 );
            push @stack, $result;
        }
    }
    return pop @stack;
}