Walkthrough of an RPL program for an RPN programmer
|
08-18-2018, 09:17 PM
(This post was last modified: 08-19-2018 02:33 PM by Thomas Klemm.)
Post: #1
|
|||
|
|||
Walkthrough of an RPL program for an RPN programmer
(04-06-2018 11:59 AM)Maximilian Hohmann Wrote: I would consider myself a random person in that respect (*), but I have so far failed to understand even a single program written in RPL. I don't know if I really can't understand it or if it is because I don't want to... because whenever I see anything like <<DUP ROT ... I instantly feel the urge to zap it away, just the way I would do with commercial breaks on TV or whenever a hip hop song is played on the radio. I can give you a walkthrough of the following program for the HP-48G: (08-18-2018 04:41 PM)Thomas Klemm Wrote: ( mm dd yyyy -- dow ) To make you familiar with the context please read my original post. Stack Commands The aforementioned commands DUP, ROT, SWAP are well know among RPN programmers but we use different names: DUP is ENTER but without disabling stack lift. ROT is R↑ but for a 3-level stack. SWAP is X<>Y. OVER is RCL Y if you know the HP-41. DROP is something like CLX followed by R↓. All these commands stem from Forth so it's not something specific to RPL. Stack Diagrams There's an infinite stack (well not really) with RPL. This is nice: we can push stuff on it and don't have to care until later. However we don't have automatic copy of T. The stack may be empty. This is what we get with the DEL command. You may be familiar with stack diagrams that show the state of the stack with each command. For instance to calculate: \(3\times(4 + 5)\) Key X Y Z T 3 3 ENTER 3 3 4 4 3 ENTER 4 4 3 5 5 4 3 + 9 3 × 27 But with Forth the order of the stack is reversed in diagrams. The top of stack is the rightmost element. But that's exactly the order you enter the data. So on a HP-48G you can use the ENTER key to separate numbers: 3 ENTER : 3 4 ENTER : 3 4 5 ENTER : 3 4 5 + : 3 9 × : 27 Or then you can use a space to separate numbers: 3 4 5 + : 3 9 × : 27 Input ( mm dd yyyy -- dow ) This is just the order we fill the stack before calling the function that returns dow, the day of week. For today (i.e. August, 18th 2018) we would use: 8 ENTER 18 ENTER 2018 Or then: 8 18 2018 In both cases we end up with the following stack diagram: 8 18 2018 Initialisation We have to modify the month and year in case of January and February and then calculate both the year of the century and the zero-based century. First we bring the month mm to the top of the stack: Code: ROT @ dd yyyy mm Now we check if that value is smaller than 3. Contrary to RPN the commands always consume the parameters even in case of comparisons. Since we need the value later we have to duplicate it first: Code: IF DUP 3 < Here are the steps in slow motion: Code: IF @ dd yyyy mm The result (either 0 or 1) is then consumed by the IF statement and we branch to the correct case: Code: THEN 12 + SWAP 1 - Let's split that up into multiple lines: Code: THEN @ dd yyyy mm The other case is much simpler: Code: ELSE @ dd yyyy mm And then we finish the IF statement with: Code: END We just have to make sure that at the end of both branches the order of the elements is the same. year of the century For this we just have to calculate: yyyy MOD 100. But since we need that value again later we better make a copy beforehand: Code: DUP @ dd mm YYyy YYyy zero-based century We take the integer part of yyyy after dividing it by 100: Code: SWAP @ dd mm yy YYyy Local Variables The next line creates a new context for local variables. They are assigned in the same order that they appear on the stack. Code: → q m K J Thus we end up with: q = dd m = mm K = yy J = YY The context is marked with these guillemets: Code: « This step consumed the stack completely so it's now empty. List of Weekdays We push that list now but we need it only later: Code: { "Saturday" Calculating the Zeller's congruence The next steps should be easy to understand since it's exactly how you'd calculate the expression on any RPN calculator: \(h=\left(q+\left\lfloor {\frac {13(m+1)}{5}}\right\rfloor +K+\left\lfloor {\frac {K}{4}}\right\rfloor +\left\lfloor {\frac {J}{4}}\right\rfloor -2J\right){\bmod {7}}\) Code: q This leaves us with the following stack diagram: weekdays h Mapping to Day of Week Since the index of lists start with 1 we have to adjust that: Code: 1 + GET I assume that you can figure out by yourself what GET does. Next Steps Debugger I highly recommend to run the program in the debugger and single step through it. So you can follow the changes of the stack with each step. Control Structures There are other control structures that you could explore: CASE, START, FOR, DO, WHILE List Operations There's a good reason this language has Lisp in it's acronym. It's worth to make you familiar with lists and their powerful operations. It allows to calculate Gauss's shoelace formula with just a few lines: Code: « Kind regards Thomas |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 3 Guest(s)