[SPOILER] RPN calculator
Rod Adams <[email protected]> Fri, 01 Oct 2004 11:00:59 -0500
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Message-ID | <[email protected]> |
This was my 20 minute perl solution. Not documented, but should be
fairly easy to follow.
I think it does all the extra features except the hex/oct/bin items.
One should be able to add a 'use Math::Trig;' and then expand the
@perl_unary_ops accordingly if they wanted more trig functions.
-- Rod
#!/usr/bin/perl
my @stack = ();
my @perl_binary_ops = qw{ + - / * % ** << >> & ^ | };
my @perl_unary_ops = qw{ ++ -- sin cos abs int exp log sqrt atan2 rand };
print "> ";
while (<>) {
chomp;
my @cmds = split;
while (@cmds) {
local $_ = my $cmd = lc shift(@cmds);
# push numbers
/^[+-]?\d+(?:\.\d+)?$/ and do {
push @stack, $_;
next; };
# perl binary ops
if (grep $_ eq $cmd, @perl_binary_ops) {
defined($y = spop()) or last;
defined($x = spop()) or last;
push @stack, eval "$x $_ $y";
next;
}
# perl unary ops
if(grep $_ eq $cmd, @perl_unary_ops) {
defined($x = spop()) or last;
push @stack, eval "$_ $x";
next;
}
# misc commands
/^drop$/ and do {
defined(spop()) or last;
next; };
/^swap$/ and do {
defined($x = spop()) or last;
defined($y = spop()) or last;
push @stack, $x, $y;
next; };
/^clear$/ and do {
@stack = ();
next; };
/^dup$/ and do {
defined($y = spop()) or last;
push @stack, $y, $y;
next; };
/^rolld$/ and do {
defined($n = spop()) or last;
if ($n > @stack) {
print "Stack Underflow\n";
@stack = ();
last;
}
defined($x = spop()) or last;
splice(@stack, -$n, 0, $x);
next; };
/^roll$/ and do {
defined($n = spop()) or last;
if ($n > @stack) {
print "Stack Underflow\n";
@stack = ();
last;
}
push @stack, splice(@stack, -$n-1, 1);
next; };
/^q/ and do {
exit; };
print "Bad Command: $_\n";
last;
}
# print stack
for ($x = 0 ; $x <= $#stack ; ++$x) {
print $#stack-$x, ': ', $stack[$x], "\n";
}
print "> ";
}
sub spop {
return pop @stack if @stack;
print "Stack Underflow\n";
return undef;
}
__END__