Forum Discussion
LBROWN7
Oct 12, 2023Brass Contributor
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
.. 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
- 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
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) ))
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 ) ))