Forum Discussion
Excel LAMBDA RPN Programming Challenge
Hi All:
There is a website called rosettacode.org (currently offline) that is an archive of the same problem solved in large number of computer-languages( approximately 96 – listed below) . Excel LAMBDA is not among them!
rosettacode.org is currently offline, but is accessible via the internet archive
https://web.archive.org/web/20230223024944/https:/rosettacode.org/wiki/Parsing/RPN_calculator_algorithm
.. Hopefully it will be back.
The common problem for all 96 languages is as follows:
Task
Create a stack-based evaluator for an expression in reverse Polish notation (RPN) that also shows the changes in the stack as each individual token is processed as a table
task: 3 4 2 * 1 5 - 2 3 ^ ^ / +
I have developed a program in Google Sheets LAMBDA that solves – but getting it to work in Excel LAMBDA is beyond me. I believe the problem has to do with the fact that SCAN function in Excel operates differently than I expect/understand.
Others ( @Sergei Baklan , @ Peter Bartholomew et. Al. ), I am sure could generate much more elegant solutions, that could be posted to this site once it comes back on line. ( I will post my solution that works in Google Sheets below).
Oh, one last point, I think it would be wise to develop a solution that works in both Excel and Google Sheets – as its likely whatever spreadsheet LAMBDA program is posted publicly will be tried by people who do not have Office-365, and will likely try it on Sheets. (this makes the problem interesting).
Below is the output of my solution, showing the stack as each token is pushed onto it.
POSTFIX EVALUATOR | ||||||
POSTFIX: | 3 4 2 * 1 5 - 2 3 ^ ^ / + | |||||
RESULT: | 3.00012207 | |||||
STEPS | STACK | |||||
[ 1 ] 3 | 3 | |||||
[ 2 ] 4 | 3 | 4 | ||||
[ 3 ] 2 | 3 | 4 | 2 | |||
[ 4 ] * | 3 | 8 | ||||
[ 5 ] 1 | 3 | 8 | 1 | |||
[ 6 ] 5 | 3 | 8 | 1 | 5 | ||
[ 7 ] - | 3 | 8 | -4 | |||
[ 8 ] 2 | 3 | 8 | -4 | 2 | ||
[ 9 ] 3 | 3 | 8 | -4 | 2 | 3 | |
[ 10 ] ^ | 3 | 8 | -4 | 8 | ||
[ 11 ] ^ | 3 | 8 | 65536 | |||
[ 12 ] / | 3 | 0.0001220703125 | ||||
[ 13 ] + | 3.00012207 | |||||
As an aside, here are the 96 programming languages:
mw-content-text, 11l, 360_Assembly, Action!, Ada, ALGOL_68, ANSI_Standard_BASIC, ANTLR, Java, AutoHotkey, BBC_BASIC, Bracmat, C, C#, C++, Ceylon, Clojure, CLU, COBOL, Common_Lisp, D, EchoLisp, Ela, Erlang, F#, Factor, Forth, Fortran, FreeBASIC, FunL, Go, Groovy, Haskell, Icon_and_Unicon, J, Alternate_Implementation, Java_2, JavaScript, jq, Julia, Kotlin, Lambdatalk, Liberty_BASIC, Lua, M2000_Interpreter, Mathematica/Wolfram_Language, Maxima, Output, MiniScript, N/t/roff, Classically-oriented_version, Output_2, Modern_version, Output_3, NetRexx, Nim, Objeck, OCaml, Oforth, ooRexx, PARI/GP, Output_4, Perl, Phix, PHP, PicoLisp, PL/I, PL/SQL, PowerShell, Prolog, Python, Version_1, Version_2, Quackery, Racket, Raku, REXX, version_1_2, version_2_2, version_3_(error_checking), Ruby, Run_BASIC, Rust, Scala, Sidef, Sinclair_ZX81_BASIC, Swift, Tcl, UNIX_Shell, Output_5, VBA, V_(Vlang), Wren, Xojo, XPL0, zkl
3 Replies
- LBROWN7Brass Contributor
Below is my solution to the RPN Programming problem.
It works in Sheets. But returns a CALC error in Excel.
I suspect my problem is with the SCAN function in Excel which differs from what I expect/understand.=LAMBDA(rpn_string, LET( _100, "RPN Calculator: https://www.rosettacode.org/wiki/Parsing/RPN_calculator_algorithm", SPLIT2_L, LAMBDA(string, delimiters, LET( _0, "SPLIT", _00, "Equivalent of Google Sheets Split funciton", _10, "with 'split by each' set to true ", _20, "see Google Sheets SPLIT documentation", _30, "", chars, MAKEARRAY(1, LEN(string), LAMBDA(ROW, COL, MID(string, COL, 1))), result, REDUCE( "", chars, LAMBDA(acc, cv, LET( acclen, ROWS(acc), isdelim, LAMBDA(v, ISNUMBER(FIND(v, delimiters))), concat2lastrow, LAMBDA(update, MAKEARRAY( acclen, 1, LAMBDA(row, col, INDEX(acc, row, col) & IF(row = acclen, update, "")) ) ), addblankrow, LAMBDA(IF(INDEX(acc, acclen, 1) = "", acc, VSTACK(acc, ""))), new_acc, IF(isdelim(cv), addblankrow(), concat2lastrow(cv)), new_acc ) ) ), MAP(TOROW(result), LAMBDA(v, IF(ISNUMBER(v + 0), (v + 0), v))) ) ), Lpad_L, LAMBDA(str, out_len, IF(LEN(str) < out_len, REPT(" ", out_len - LEN(str)), "") & str), expr_L, LAMBDA(op, x, y, CHOOSE(FIND(op, "+-*/^"), y + x, y - x, y * x, y / x, y ^ x)), tokens_v, SPLIT2_L(rpn_string, " "), parse_rpm_m, SCAN( "", tokens_v, LAMBDA(acc_v, c, IF( ISNUMBER(c), (IF(acc_v = "", HSTACK(c), VSTACK(acc_v, c))), LET( stack_rows, ROWS(acc_v), expression, expr_L(c, INDEX(acc_v, stack_rows), INDEX(acc_v, stack_rows - 1)), IF( stack_rows - 2 = 0, expression, VSTACK( MAKEARRAY(stack_rows - 2, 1, LAMBDA(r, c, INDEX(acc_v, r, c))), expression ) ) ) ) ) ), result_1, TRANSPOSE(parse_rpm_m), result_2, MAP( SEQUENCE(COLUMNS(tokens_v)), LAMBDA(i, HSTACK(" [ " & Lpad_L(i, 2) & " ] " & INDEX(tokens_v, i), INDEX(result_1, i))) ), result_3, VSTACK( {"POSTFIX EVALUATOR "}, HSTACK("POSTFIX" & ":", TRIM(rpn_string)), HSTACK("RESULT" & ":", TRIM(INDEX(result_1, ROWS(result_1)))), {" ", " "}, {"STEPS", "STACK "}, result_2 ), result_4, MAP(result_3, LAMBDA(c, IF(ISERROR(c), "", c))), result_4 ) )("3 4 2 * 1 5 - 2 3 ^ ^ / +")
Below is the outputPOSTFIX EVALUATOR
POSTFIX:
3 4 2 * 1 5 - 2 3 ^ ^ / +
RESULT:
3.00012207
STEPS
STACK
[ 1 ] 3
3
[ 2 ] 4
3
4
[ 3 ] 2
3
4
2
[ 4 ] *
3
8
[ 5 ] 1
3
8
1
[ 6 ] 5
3
8
1
5
[ 7 ] -
3
8
-4
[ 8 ] 2
3
8
-4
2
[ 9 ] 3
3
8
-4
2
3
[ 10 ] ^
3
8
-4
8
[ 11 ] ^
3
8
65536
[ 12 ] /
3
0.0001220703125
[ 13 ] +
3.00012207
- SergeiBaklanDiamond Contributor
Or
rpn = LAMBDA(str, LET( arr, TEXTSPLIT(str, " "), operand, LAMBDA(op, pair, LET( a, --INDEX(pair, 1, 1), b, --INDEX(pair, 1, 2), SWITCH( op, "*", a*b, "-", a-b, "^", a^b, "/", a/b, "+", a+b ) ) ), operation, LAMBDA(a,v, IF( ISNUMBER(--v), HSTACK(a, v), HSTACK(DROP(a,,-2), operand(v, (TAKE(a,,-2))) ) ) ), REDUCE( "Result:", arr, operation) )) - SergeiBaklanDiamond Contributor
As variant
rpn = LAMBDA(str, LET( arr, TEXTSPLIT(str, " "), mpl, LAMBDA(pair, INDEX(pair,1,1)*INDEX(pair,1,2) ), sbs, LAMBDA(pair, INDEX(pair,1,1)-INDEX(pair,1,2) ), pow, LAMBDA(pair, INDEX(pair,1,1)^INDEX(pair,1,2) ), div, LAMBDA(pair, INDEX(pair,1,1)/INDEX(pair,1,2) ), pls, LAMBDA(pair, INDEX(pair,1,1)+INDEX(pair,1,2) ), DROP( REDUCE(0, arr, LAMBDA(a,v, IF( ISNUMBER(--v), HSTACK(a,v), IF( v="*", HSTACK( DROP(a,,-2), mpl( TAKE(a,,-2) )), IF( v="-", HSTACK( DROP(a,,-2), sbs( TAKE(a,,-2) )), IF( v="^", HSTACK( DROP(a,,-2), pow( TAKE(a,,-2) )), IF( v="/", HSTACK( DROP(a,,-2), div( TAKE(a,,-2) )), IF( v="+", HSTACK( DROP(a,,-2), pls( TAKE(a,,-2) )), )))))) ) ), ,1 ) ))