#!/usr/bin/perl -- use strict; use warnings; my $op = shift @ARGV; my $minmax = '$result ? $_[0] : $_[1];'; my $settruth = '$result ? 1 : 0;'; my %ops = ( 'add' => { 'op' => '+' }, 'multiply' => { 'op' => '*' }, 'subtract' => { 'op' => '-' }, 'divide' => { 'op' => '/' }, 'lesser' => { 'op' => '<' }, 'greater' => { 'op' => '>' }, 'power' => { 'op' => '**' }, 'xor' => { 'op' => '&&', 'pre' => '$_[0] = ! $_[0];' }, 'all' => { 'op' => '&&', 'post' => $settruth }, 'none' => { 'op' => '||', 'post' => $settruth, 'last' => '$tot = ! $tot; $tot += 0;' }, 'any' => { 'op' => '||', 'post' => $settruth }, 'min' => { 'op' => '<', 'post' => $minmax }, 'max' => { 'op' => '>', 'post' => $minmax }, 'mean' => { 'op' => '+', 'last' => '$tot /= scalar (@_ + 1);' }, 'geomean' => { 'op' => '*', 'last' => '$tot = $tot ** ( 1 / scalar (@_ + 1) );' }, 'equal' => { 'op' => '-', 'post' => '$result = $result ? 0 : $_[1];', 'last' => 'local $" = "||"; $tot = 1 if 0 == $tot && 0 == eval "@_";'} ); sub make_op { my $op = shift; my $result = 0; $ops{$op}{'sub'} = sub { ( eval $ops{$op}{'pre'} ) if defined $ops{$op}{'pre'}; $result = ( eval $_[0] . $ops{$op}{'op'} . $_[1] ) + 0; $result = ( eval $ops{$op}{'post'} ) if defined $ops{$op}{'post'}; return $result; }; } sub do_op { my $op = shift; my $tot = shift; make_op( $op ) unless ( exists $ops{$op}{'sub'} && defined $ops{$op}{'sub'} && ref $ops{$op}{'sub'} eq 'CODE' ); foreach ( @_ ) { $tot = $ops{$op}{'sub'}( $tot, $_ ); } if ( exists $ops{$op}{'last'} ) { eval $ops{$op}{'last'}; } return $tot; } printf "%-0.03f\n", do_op( $op, @ARGV );