# HP Forums

Full Version: HHC 2013 RPN Programming Challenge - Final Thought
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

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?

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

Which 65 did you use :-)

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

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

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.

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?

doh!

Correct!

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