Forum Discussion

LBROWN7's avatar
LBROWN7
Brass Contributor
Oct 12, 2023

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

  

 

 

 

 

  • LBROWN7's avatar
    LBROWN7
    Brass 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 output

    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

        
          

     

     

    • LBROWN7 

      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)
      ))
    • LBROWN7 

      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 )
      ))

Resources