HHC 2013 RPN Programming Challenge - Final Thought



#2

In case anyone wants a diversion from the Prime discussion, I had one final thought about the HHC 2013 RPN Programming Challenge that I’ve been meaning to bring up. (I’m probably the only person who spent much time on the challenge after about September 25, but I enjoy them and so tend to keep fiddling with them long after the conference.) I don’t have any new programming revelations or insights beyond what the group presented in the few days after conference, just this: I believe all of the solutions presented at the forum (except Pauli’s here) converted the octal value one digit at a time, from left to right. At some point, I began to wonder if it would be more accurate to convert the number from right to left, i.e., start with least significant digit. It seemed to me that conversion from right to left would more accurately get the carry correct from the far right digits. Perhaps that is not a real concern, but I decided to attempt to write a program to do so, probably just for the fun of it. While I was able to write a 15 step wp34s program to convert from left to right, the best I have done so far for right-to-left conversion is 27 steps, as follows:

Step	Command		Comment
001 ENTER duplicate entered value
002 EXPT extract exponent
003 +/- change sign of exponent
004 #011 enter 11
005 + add 11 to exponent
006 #008 enter 8
007 x<>Y swap
008 y^x calculate multiple of 8 for least significant digit
009 x<>Y swap
010 MANT extract mantissa of N
011 SDL 10 multiply by 1E10
012 #000 enter 0 for initial converted value
013 <>YYZX get stack in right order
014 FRAC take fractional part (only one digit)
015 STO-Y subtract from original to get integer part in Y
016 SDL 01 multiply fractional part by 10
017 RCL/ Z divide by current power of 8
018 STO+ T add to current sum
019 CL x Clear X, disable stack lift
020 #008 enter 8
021 STO/ Z divide into current power of 8 for next power
022 Rdown roll down
023 SDR 01 divide by 10
024 ENTER duplicate N
025 x=/=0? check if done
026 BACK 012 loop back until done
027 RCL T done, recall converted value

The above is for a 12-digit entry, since that’s the most you can enter on a wp34s. If you enter a value with less than 12 digits, it dutifully converts the trailing zeroes. Although I did not intend this result, this program seems to work for any value that can be entered into a wp34s, i.e., is not limited to 0 <= n <= 1. It does of course assume a valid octal input, i.e. no 8s or 9s.

I note that this program does produce what Pauli declares to be the “True” answer for an input of 1e-95, so perhaps it is more accurate?


#3

Here it is. Works.


LBL
A
STO
1
1
0
STO
8
CLX
LBL
B
RCL
1
1
0
X
ENTER
F
INT
STO
4
-
STO
1
RCL
4
1
1
RCL
8
-
8
X<>Y
g
Y^X
/
RCL
3
+
STO
3
g
DSZ
GTO
B
RCL
3
R/S

Please feel free to improve upon this. :-)


#4

Which 65 did you use :-)

#5

Hi Gene,

I don't have a 65 handy (or an emulator or simulator) so I cannot test directly. I figured it should be more-or-less directly translatable to a wp34s program, so I thought I'd try that. But first I tried to step through the listing to make sure I understand it. You seem to be collecting the answer in register 3, yet I find no step that initializes it to zero. Did I miss some trick to initialize, or is there supposed to be a

STO

3

after the CLX in step 9?


#6

doh!

Correct!


#7

In that case, it works great!* At least as implemented in this wp34s program that only collapses the HP-65 two-step instructions for things like LBL A and RCL 3 into single step equivalents, but does not take advantage of any other wp34s improvements:

Step	Command	Comment
001 LBL A Label Declaration A
002 STO 01 store input value in register 1
003 1 enter 1…
004 0 enter… 0 for 10
005 STO 08 store 10 in register 8
006 CLX Clear x, disable stack lift
007 STO 03 reset register 3
008 LBL B Label Declaration B
009 RCL 01 Recall current value from register 1
010 1 enter 1…
011 0 enter… 0 for 10
012 X multiply by 10
013 ENTER duplicate value
014 INT take integer part
015 STO 04 store X value in register 4
016 - subtract frational part from N for next N
017 STO 01 store X value in register 1, next N
018 RCL 04 Recall register 4, current digit
019 1 enter 1…
020 1 enter… 1 for 11
021 RCL 08 Recall register 8
022 - subtract
023 8 enter 8
025 X<>Y swap
026 Y^X Y^X
027 / divide into current digit
028 RCL 03 register 3, current sum
029 + add
030 STO 03 store new sum back in register 3
031 DSZ 08 decrement index, use register 8
032 GTO B loop back…
033 RCL 03 when done, recall converted value
034 R/S stop

* - well, works great with some input limitations that don't quite meet the 0 <= n <= 1 range specified by the Master of the Challenge :-)

#8

My solution was digit at a time right to left, albeit with some limitations on the number of decimal places and the maximum value.

- Pauli


#9

After I developed my right-to-left conversion program, I thought I’d better re-check the solutions presented here before I asserted that they were all left-to-right. (I admit to not having studied them all in detail on first reading.) Your program looked similar to others that did it left-to-right, but then I noticed the MOD instruction and deduced you were doing it right-to-left.

Regarding your use of MOD, I decided to try that instead of my method using FP to strip off one digit right of the decimal and then multiplying by 10. Doing so required me to use a (local) storage register, but I was also able to make it one step shorter, down to 26:

001	ENTER		duplicate entered value
002 EXPT extract exponent
003 +/- change sign of exponent
004 #011 enter 11
005 + add 11 to exponent
006 #008 enter 8
007 x<>Y swap
008 y^x calculate multiple of 8 for least significant digit
009 x<>Y swap
010 MANT extract mantissa of N
011 SDL 11 multiply by 1E11
012 LocR 001 create one local register to accumulate sum
013 RCL X get stack in right order
014 #010 enter 10
015 RMDR extract units digit using RMDR
016 STO-Y subtract from original to remove units digit
017 RCL/ Z divide by current power of 8
018 STO+ .00 add to current sum
019 CL x Clear X, disable stack lift
020 #008 enter 8
021 STO/ Z divide into current power of 8 for next power
022 Rdown roll down
023 SDR 01 divide by 10
024 x=/=0? check if done
025 BACK 012 loop back until done
026 RCL .00 done, recall converted value

Of course if I use a local storage register in my original version, I also save a step. The local register starts at zero, and so eliminates the need to enter a zero, which then saves a stack manipulation step later:

001	ENTER		duplicate entered value
002 EXPT extract exponent
003 +/- change sign of exponent
004 #011 enter 11
005 + add 11 to exponent
006 #008 enter 8
007 x<>Y swap
008 y^x calculate multiple of 8 for least significant digit
009 x<>Y swap
010 MANT extract mantissa of N
011 SDL 10 multiply by 1E10
012 LocR 001 create one local register to accumulate sum
013 RCL X get stack in right order
014 FRAC take fractional part (only one digit)
015 STO-Y subtract from original to get integer part in Y
016 SDL 01 multiply fractional part by 10
017 RCL/ Z divide by current power of 8
018 STO+ .00 add to current sum
019 CL x Clear X, disable stack lift
020 #008 enter 8
021 STO/ Z divide into current power of 8 for next power
022 Rdown roll down
023 SDR 01 divide by 10
024 x=/=0? check if done
025 BACK 012 loop back until done
026 RCL .00 done, recall converted value

Assuming I understand it correctly, I like your method of adding a digit, then dividing by 8 to push the result one octal digit. Eliminates the need to raise 8 to some power and keep a running multiple of 8. I think I’ll see if I can work that into my method to handle all 12 digit inputs.

Improved version, using Pauli's method to convert the mantissa from right to left, then shift that left or right as needed based on the exponent by raising 8 to the appropriate power:

1	LocR 002	create two local registers
2 STO .01 store entered value
3 MANT extract mantissa of N
4 SDL 11 multiply by 1E11
5 RCL X duplicate value
6 #010 enter 10
7 RMDR extract units digit using RMDR (to work for neg)
8 STO-Y subtract from original to remove units digit
9 STO+ .00 add to current sum
10 #008 enter 8
11 STO/ .00 push sum one octal digit right
12 RCL Z Recall previous value less units
13 SDR 01 divide by 10
14 x=/=0? check if done
15 BACK 010 loop back until done
16 x<>Y swap
17 RCL .01 recall original entry
18 EXPT extract exponent
19 INC X add 1 to exponent
20 y^X 8^(EXPT+1)
21 RCLx .00 recall converted mantissa value, multiply by 8^p

Last and maybe least, the following version converts the maintissa rigth to left, then shifts the result left or right as required by repeatedly multiplying by 8 or 1/8. The thought is that repeated multiplication may be more accurate than raising 8 to some power.

11	LocR 002	create two local registers
2 STO .01 store entered value
3 MANT extract mantissa of N
4 SDL 11 multiply by 1E11
5 RCL X duplicate value
6 #010 enter 10
7 RMDR extract units digit using RMDR (to work for neg)
8 STO-Y subtract from original to remove units digit
9 STO+ .00 add to current sum
10 #008 enter 8
11 STO/ .00 push sum one octal digit right
12 RCL Z Recall previous value less units
13 SDR 01 divide by 10
14 x=/=0? check if done
15 BACK 010 loop back until done
16 x<>Y swap
17 RCL .01 recall original entry
18 EXPT extract power of 10
19 x=/= 0? check if exponent is zero
20 SKIP 001 if not zero, skip to SIGN
21 INC X if zero, set equal to 1
22 SIGN get sign of exponent
23 y^X raise 8 to 1 or -1 power to get 8 or .125 multiplier
24 RCL .01 recall original entry
25 EXPT extract power of 10
26 INC X add 1 to exponent
27 ABS take absolute value for loop index
28 x=0? check if loop index equals zero
29 SKIP 005 if so, done, go to end
30 RCL Y recall 8 or .125
31 STOx .00 multiply by 8 or .125 to shift left or right
32 x<>Y swap
33 DEC X decrement index
34 BACK 006 go back for next shift
35 RCL .00 recall answer

edit 1 - changed MOD to RMDR in first program to make it work with negative inputs.

edit 2 - added new version

edit 3 - added final version


Edited: 23 Oct 2013, 8:46 a.m.


Possibly Related Threads...
Thread Author Replies Views Last Post
  [PRIME] RPN: another attempt at returning more than one value to the RPN stack Marcus von Cube, Germany 5 339 11-05-2013, 02:44 AM
Last Post: Marcus von Cube, Germany
  HP Prime 2013 8 13. Rev:5106 bluesun08 2 178 09-28-2013, 11:05 AM
Last Post: debrouxl
  HHC 2013 programming contest winners Brian Walsh 52 1,835 09-26-2013, 11:39 PM
Last Post: David Hayden
  Box left at HHC Tim Wessman 1 180 09-26-2013, 11:05 PM
Last Post: Wlodek Mier-Jedrzejowicz
  HHC 2013 speakers' files Joe Horn 2 193 09-26-2013, 02:51 AM
Last Post: Geoff Quickfall
  HHC 2013 Day 2 Highlights Eddie W. Shore 6 386 09-23-2013, 04:03 PM
Last Post: Kimberly Thompson
  HHC 2013: Day 1 Highlights Eddie W. Shore 28 975 09-23-2013, 03:22 PM
Last Post: Brad Barton
  HHC / HP Museum Programming Contest for RPN and RPL machines Gene Wright 18 723 09-22-2013, 09:39 AM
Last Post: Miguel Toro
  HHC 2013 room numbers David Hayden 2 171 09-20-2013, 05:34 PM
Last Post: sjthomas
  Flash Flood Warning: 9/16/2013 (One Week from HHC13) Eddie W. Shore 8 424 09-17-2013, 09:20 PM
Last Post: Craig Ruff

Forum Jump: