TypeScript's type system, 206 205 bytes
//@ts-ignore
type F<C,S=[0,0]>=[S,C]extends[[infer A,infer B,...infer V],[infer I,...infer R]]?F<R,I extends string?[I,...S]:[...[[B],[A,A,B],[B,A],[`${A}${B}`],B extends`${A}${infer Z}`?[Z]:0][I],...V]>:S
Try it at the TS playground
This is a generic type F<C>
which takes input as a tuple of items which are either unary numbers as strings of 1s, or numbers 0 to 4 for the 5 commands:
num |
function |
0 |
Pop |
1 |
Duplicate |
2 |
Swap |
3 |
Add |
4 |
Subtract |
This solution works identically to the one below, only it skips the step of splitting on spaces, and indexes into an array instead of a dictionary, so it ends up quite a bit shorter.
TypeScript’s type system, 324 309 251 220 bytes
//@ts-ignore
type F<C,S=[0,0]>=[S,C]extends[[infer A,infer B,...infer V],`${infer I} ${infer R}`]?F<R,I extends`1${any}`?[I,...S]:[...{p:[B],d:[A,A,B],x:[B,A],a:[`${A}${B}`],s:B extends`${A}${infer Z}`?[Z]:0}[I],...V]>:S
Try it at the TS playground
This is a generic type F<C>
which takes input as a string type of space separated commands or unary numbers, space terminated. Output in unary, first element is top of stack.
Commands:
name |
function |
a |
Add |
s |
Subtract |
x |
Swap |
p |
Pop |
d |
Duplicate |
I was surprised by how short this was when it was 100 bytes longer than it is now, so now I'm really surprised.
Explanation:
type F<
// C is the input string type
C,
// S is the stack, starts with two useless elements
S=[0,0],
>=[S,C]extends[
// get the top 2, A and B, and the rest V, of the stack
[infer A,infer B,...infer V],
// get the first word I and the rest R of C
`${infer I} ${infer R}`
]
// recurse, setting C to R, and setting S to...
?F<R,
// does I start with a 1?
I extends`1${any}`
// if so, prepend it to S
?[I,...S]
// otherwise, it's a command; index into this object
// to replace the top 2 of the stack:
:[...{
// pop- just the second
p:[B],
// dup- first twice, then second
d:[A,A,B],
// swap: second, then first
x:[B,A],
// add: concatenate the first and second
a:[`${A}${B}`],
// subtract: the second with the first taken away
s:B extends`${A}${infer Z}`?[Z]:0
// then append V
}[I],...V]
>
// if C is empty (no more commands are left), return S
:S
10 0 -
anyway) \$\endgroup\$