Background
This challenge is based on a personal project I did, UnitDC. This challenge is a super-miniaturized version of UnitDC.
Challenge
Please write a simple unit-aware calculator that evaluates a sequence of positive integers, units and operators in RPN (postfix) notation, while checking whether the units are compatible with each other.
Tokens
Numbers
Numbers are all positive integers in the form "[0-9]+".
Units
Pops a value off the stack and set the unit of that quantity. For simplicity, units are represented by a single lower-cased letter. All letters are considered base units. Additionally it is guaranteed that the top of stack will have a quantity with no unit when the unit token is encountered.
Operators
For simplicity there are only three operators, +, * and /. All pop 2 values off the stack and push one back. It is guaranteed that the stack will not underflow.
- For the + operator, you should check whether the two operands are of the same unit, if not you should report error.
- For the * and / operator, you should update the units accordingly (sum up or subtract the exponents of rhs to lhs). All divisions are guaranteed to be whole.
I/O
You can choose take Input in any of the following forms, from STDIN, function arguments or a memory location:
- A string of tokens, separated by space.
- An array of token strings.
At the end of the evaluation, print to STDOUT or return as value the contents of the stack (top to bottom or bottom to top) in one of the following forms:
- An array of quantities.
- A string concatenation of quantities, separated by space.
where quantity is a string represented by the regex "^\d+([a-z](-?\d+))*$". The notation is simply the concatenation of the number, the letter for each unit and then its exponents. For example "1m2s-3" means \$1m^2s^{-3}\$. Valid representations include "1" "1g1" "1m1s-2". "1a0" is INVALID (no zero exponents). Ordering of the units are not important.
If an error is encountered during the evaluation, either output '*' and nothing else, or crash, or exit with a non zero code.
Examples
I: 1
O: 1
I: 1 s
O: 1s1
I: 1 s 2 m +
O: *
I: 1 m 1 s / 1 m 1 s / +
O: 2s-1m1
I: 1 s 2 s * 1 s
O: 2s2 1s1
I: 1 s 1 s /
O: 1
Note: *1s0 is not acceptable here*
I: 1 m 1 s / 2 m 2 s / +
O: 2m1s-1
I: 1 s 1 s / 1 +
O: 2
I: 1 m 1 m / s
S: 1s1
I: 5 s 2 *
S: 10s1
I: 5 s 2 +
O: *
Reference Implementation (Rust)
This is a small reference implementation I made, this program accepts multiple lines of inputs but you only need to accept one input.
Related
Similar questions that may be helpful:
Scoring
This is code-golf, shortest code wins!
1 m 1 m / s
valid? \$\endgroup\$1g
does not meet the requirement of regex. Do you mean1g1
or do you mean\d*
in regex? \$\endgroup\$