HP Forums
HP 48G - Edit List - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Calculators (and very old HP Computers) (/forum-3.html)
+--- Forum: General Forum (/forum-4.html)
+--- Thread: HP 48G - Edit List (/thread-17378.html)



HP 48G - Edit List - MNH - 08-22-2021 03:40 AM

@ { 11 12 13 14 } → { 11 12 14 }
@ Delete the object in position 3 and return a list in original order.
@ ELIST (Edit list)

\<< { 11 12 13 14 }
13 \-> list object
\<< list DUP object
POS SWAP OBJ\-> 1 +
ROLL ROLLD DROP
SWAP DEPTH \->LIST
\>>
\>>

Can I make this program better? I have not tested it on other lists. I would like to be able to delete an object in any position in any list, regardless of the order of the objects.


RE: HP 48G - Edit List - John Keith - 08-22-2021 03:02 PM

It's a bit unclear from your post whether you want to remove an object by its position or by its value but here are a couple of suggestions.

With the list on level 2 and the position on level 1:

Code:

\<< DUP2 1 SWAP 1 - SUB ROT ROT 1 + OVER SIZE SUB +
\>>

With the list on level 2 and the object to search for on level 1 as in your example, just a small addition to the program above:

Code:

\<< OVER SWAP POS DUP2 1 SWAP 1 - SUB ROT ROT 1 + OVER SIZE SUB +
\>>

As a side note, my opinion is that DEPTH is a command that should be used carefully if ever in programs. One basic principal of RPL programming is that a program should take a specific number of objects from the stack and not affect other objects that may be above them on the stack. The program fragment DEPTH \->LIST violates that principle by sweeping up everything on the stack regardless of its purpose or origin.


RE: HP 48G - Edit List - MNH - 08-23-2021 12:02 AM

(08-22-2021 03:02 PM)John Keith Wrote:  With the list on level 2 and the position on level 1:

Code:

\<< OVER SWAP POS DUP2 1 SWAP 1 - SUB ROT ROT 1 + OVER SIZE SUB +
\>>

Thanks, John! The second program works just fine for my purposes. Before writing my code, I considered removing the objects surrounding the object I wanted to remove and reassemble them in a new list; I thought it would be too complicated. In my effort to come up with a simple solution, I chose to use local variables. I understand your resistance to use DEPTH. I'm pretty sure that there are code samples in the AUR manual that use it. I wonder why a command was never written that edits a list in the way I want.


RE: HP 48G - Edit List - John Keith - 08-23-2021 12:52 AM

(08-23-2021 12:02 AM)MNH Wrote:  I wonder why a command was never written that edits a list in the way I want.

Most likely lack of ROM space. The 48G does add many useful features for list processing compared to the 28 or 48S but certainly there can't be enough space for every imaginable command. For the 50g there are libraries such as GoferLists and ListExt which extend list processing functions well beyond those of the 48 series.

Regarding DEPTH I did not mean to imply that it is an evil command that should not exist, but that its use in programs can be problematic. DEPTH is often useful in interactive calculations or in quick-and-dirty programs for one-off use, but questionable for most programs, especially ones that may be called by other programs.


RE: HP 48G - Edit List - John Keith - 08-23-2021 01:13 AM

For example, your program could be modified by storing the size of the list in a local variable rather than using DEPTH, since we know that the input list will be transformed into a list with 1 fewer object:

Code:

\<<  OVER SIZE \-> list object size
  \<< list DUP object
POS SWAP OBJ\-> 1 +
ROLL ROLLD DROP
SWAP size 1 - \->LIST
  \>>
\>>



RE: HP 48G - Edit List - DavidM - 08-23-2021 03:13 AM

(08-23-2021 12:52 AM)John Keith Wrote:  
(08-23-2021 12:02 AM)MNH Wrote:  I wonder why a command was never written that edits a list in the way I want.

Most likely lack of ROM space. The 48G does add many useful features for list processing compared to the 28 or 48S but certainly there can't be enough space for every imaginable command. For the 50g there are libraries such as GoferLists and ListExt which extend list processing functions well beyond those of the 48 series.

(Emphasis added by me Smile ) I think you nailed it with the space issue. List manipulation in RPL code is inherently slow due to the free-form nature of the data structure (a prologue, data objects in sequence, a token to signify the end of the data). Accessing individual elements requires stepping through the entire sequence that precedes the element in question. Speeding things up requires Saturn code, which in turn requires a lot of space.

(08-23-2021 12:52 AM)John Keith Wrote:  Regarding DEPTH I did not mean to imply that it is an evil command that should not exist, but that its use in programs can be problematic. DEPTH is often useful in interactive calculations or in quick-and-dirty programs for one-off use, but questionable for most programs, especially ones that may be called by other programs.

I agree that the use of DEPTH as presented in the original program above is problematic. It limits the usefulness of the program to situations where there is nothing else on the stack other than arguments to that function, which means it's not very accommodating.

That said, DEPTH is still very useful. The internal version of the DEPTH command is likely to be one of the most used segments of code in an RPL calculator, since pretty much every UserRPL command does an initial check of the stack depth to make sure that at least the correct number of arguments exists prior to execution. This is part of the normal structure of SysRPL code. I've rarely seen User RPL code designed to do an initial check for argument counts (and/or types), but DEPTH could be used for that purpose. I'm not advocating for people to write User RPL code in that way, mind you, just saying that it could be done. The fact that built-in commands always do this for you means that it isn't as important to do it yourself.

One of the best uses of DEPTH in User RPL code that I've seen is in comparing "before" and "after" counts of stack entries when you don't know in advance how many new stack entries may be added by some process. Consider the following program, which provides a list of the results from applying the even/odd functions in sequence for a Collatz Conjecture implementation:
Code:
\<<
   DEPTH 1 - \->  notmine     @ 1 argument on the stack is mine, the rest should be left alone
   \<<
      WHILE
         1 OVER SAME NOT      @ repeat as long as current value is not 1
      REPEAT
         IF
            DUPDUP 2 MOD      @ 0: even, 1: odd
         THEN
            3 * 1 +           @ odd: 3x+1
         ELSE
            2 /               @ even: x/2
         END
      END
      DEPTH notmine - \->LIST @ put all new stack entries into result list
   \>>
\>>

The program can't know in advance how many entries will be created, so it simply finds the delta for the before and after stack depths, and puts that count of objects into the result list. This is in fact the same method used by several of the built-in list commands for "knowing" how many objects to include in result lists.


RE: HP 48G - Edit List - John Keith - 08-23-2021 09:41 PM

(08-23-2021 03:13 AM)DavidM Wrote:  That said, DEPTH is still very useful. The internal version of the DEPTH command is likely to be one of the most used segments of code in an RPL calculator, since pretty much every UserRPL command does an initial check of the stack depth to make sure that at least the correct number of arguments exists prior to execution. This is part of the normal structure of SysRPL code. I've rarely seen User RPL code designed to do an initial check for argument counts (and/or types), but DEPTH could be used for that purpose. I'm not advocating for people to write User RPL code in that way, mind you, just saying that it could be done. The fact that built-in commands always do this for you means that it isn't as important to do it yourself.

One of the best uses of DEPTH in User RPL code that I've seen is in comparing "before" and "after" counts of stack entries when you don't know in advance how many new stack entries may be added by some process. Consider the following program, which provides a list of the results from applying the even/odd functions in sequence for a Collatz Conjecture implementation:
Code:
\<<
   DEPTH 1 - \->  notmine     @ 1 argument on the stack is mine, the rest should be left alone
   \<<
      WHILE
         1 OVER SAME NOT      @ repeat as long as current value is not 1
      REPEAT
         IF
            DUPDUP 2 MOD      @ 0: even, 1: odd
         THEN
            3 * 1 +           @ odd: 3x+1
         ELSE
            2 /               @ even: x/2
         END
      END
      DEPTH notmine - \->LIST @ put all new stack entries into result list
   \>>
\>>

The program can't know in advance how many entries will be created, so it simply finds the delta for the before and after stack depths, and puts that count of objects into the result list. This is in fact the same method used by several of the built-in list commands for "knowing" how many objects to include in result lists.

That is indeed a clever method, consider it stolen!
For programs like that, I have generally maintained a counter on level 1 and SWAP objects above the counter as they occur, then increment the counter. At the end, \->LIST puts all of the objects into a list.

Your method is undoubtedly faster since it avoids all of the swapping and incrementing.