Perlで書いたらだいぶ簡単ですね。
やっぱりサブルーチンリファレンスがあると
気持ち楽にかけます。
#!/usr/local/bin/perl package ReversePolish; use Moose; use MooseX::AttributeHelpers; has stack => ( metaclass => 'Collection::Array', is => 'rw', isa => 'ArrayRef[Int]', default => sub { +[]; }, provides => { push => 'push_number', pop => 'pop_number', }, ); __PACKAGE__->meta->make_immutable; use Scalar::Util qw(looks_like_number); my %operator = ( '+' => sub { my ($a, $b) = @_; return $a + $b; }, '-' => sub { my ($a, $b) = @_; return $a - $b; }, '*' => sub { my ($a, $b) = @_; return $a * $b; }, '/' => sub { my ($a, $b) = @_; die "Error : Zero divided\n" if $b == 0; return $a / $b; }, '%' => sub { my ($a, $b) = @_; die "Error : Zero divided\n" if $b == 0; return $a % $b; }, ); sub calc { my ($self, $input) = @_; my @inputs = split /[\s\t]/, $input; foreach my $term (@inputs) { if ( looks_like_number($term) ) { $self->push_number($term); } elsif ( exists $operator{$term} ) { my $op2 = $self->pop_number(); my $op1 = $self->pop_number(); my $val = $operator{$term}->($op1, $op2); $self->push_number($val); } else { Carp::croak("Invalid input\n"); } } my $ret_val = $self->pop_number(); Carp::croak("Error : data is left in stack\n") if scalar @{$self->stack}; return $ret_val; } package main; use Test::More; my $reverse_calcurator = ReversePolish->new(); is($reverse_calcurator->calc("1 2 +"), 3); is($reverse_calcurator->calc("3 2 -"), 1); is($reverse_calcurator->calc("9 2 *"), 18); is($reverse_calcurator->calc("91 7 /"), 13); is($reverse_calcurator->calc("91 5 %"), 1); done_testing();