exercism-perl5

Repository for my Perl 5 Exercism exercises
git clone git://git.samirparikh.com/exercism-perl5
Log | Files | Refs | README

Wordy.pm (1865B) - raw


      1 package Wordy;
      2 use strict;
      3 use warnings;
      4 use Exporter qw<import>;
      5 our @EXPORT_OK = qw<answer>;
      6 
      7 ########################################################################
      8 # PLEASE NOTE:  This solution, as posted, passes all test conditions   #
      9 # except #15 which tests whether "What is -3 plus 7 multiplied by -2?" #
     10 # returns `-8` as order of operations are to be ignored.  My solution, #
     11 # which does respect order of operations, returns `-17`, which causes  #
     12 # the test case to fail but I am marking it "Complete" nonetheless.    #
     13 ########################################################################
     14 
     15 my $pattern  = qr/(-?\d+|plus|minus|divided|multiplied)/; # to parse input
     16 my $op_regex = qr/plus|minus|divided|multiplied/;         # valid operations
     17 
     18 sub answer {
     19   my ($question) = @_;
     20   # if input does not begin with "What is":
     21   die "unknown operation" if ($question !~ m/^What is/);
     22   # find all operands and operations based on $partern and store in @m
     23   my @m = ($question =~ m/$pattern/g);
     24   die "syntax error" unless (scalar @m); # no operands or operations
     25   if (scalar @m == 1) {
     26       if ($question =~ m/-?\d+\?/) {     # 1 operand with no operation 
     27           return $m[0];
     28       } else {
     29           die "unknown operation";       # 1 operand with unknown operation
     30       }
     31   }
     32   my @stack;
     33   foreach my $i (0 .. $#m) {
     34       # check whether odd indices contain valid operation
     35       die "syntax error" if ($i%2 && $m[$i] !~ m/$op_regex/);
     36       push @stack =>
     37       #   <EXPR to evaluate>  ? if true : else
     38           $m[$i] =~ m/-?\d+/  ? $m[$i]  :
     39           $m[$i] eq 'plus'    ? '+'     :
     40           $m[$i] eq 'minus'   ? '-'     :
     41           $m[$i] eq 'divided' ? '/'     :
     42                                 '*'     ;
     43   }
     44   my $result = eval  join ' ', @stack;   # trap error in $@, if any
     45   die "syntax error" if $@;
     46   return $result; 
     47 }
     48 
     49 1;