▼
Posts: 1,830
Threads: 113
Joined: Aug 2005
I'm trying to shoehorn YATZ into the HP67/97 I'm doing fine with labels, but I'm running out of program lines. The exercise has convinced me that I can finish the port to the 33S, however, so I've shelved the 97 version for now and am working on the 33S. I'm looking for opportunities to shrink the code size while I do that, however. Below is an algorithm I developed for extracting the nth digit (counting left to right) in a number. It is rather lengthy. Can anyone see a way to shrink it? Is there another approach to this problem anyone is aware of that might be shorter?
L0001 *LBL L ! Extract the Yth digit (counting left to right) from the number in X
L0002 ENTER ! Copy the number
L0003 LOG ! Desired order is the opposite of the exponent view of the number
L0004 IP ! So calculate a complement we can subtract from the input digit position
L0005 2 ! to yield the power of ten digit position plus one. This will scale the
L0006 + ! number so the desired digit will be in the 1 power of ten position
L0007 x<>y ! Fiddle the stack for the next calculation
L0008 RDN !
L0009 x<>y ! OK, we have input digit position in X and the complement in Y
L0010  ! Difference is as stated above
L0011 x<>y !
L0012 RDN ! Number is in Y and Scaling power in X
L0013 10^x ! Divisor to bring digit down to first place to right of the decimal
L0014 / ! Divide it
L0015 FP ! Throw away higher (lower) digits.
L0016 10 ! Scale the desired digit back up
L0017 * !
L0018 IP ! Digit is now isolated
L0019 RTN
Regards, Howard
Edited: 22 Nov 2005, 1:00 p.m.
▼
Posts: 4,027
Threads: 172
Joined: Aug 2005
Hi, Howard;
Please, would you try this one? *LBL L !
ENTER !
LOG !
IP !
2 !
+ !
R^ (rollup)
 !
10^x !
/ !
FP !
10 !
* !
IP !
RTN
I test it already, and I based my code on previous stack data (if I am not wrong, the program starts with the digit to extract in Y and the number in X). After IP
2 you have: L X Y Z T
+ v i a n n
x<>y v a i n n
RDN v i n n a
x<>y v n i n a
 n I n a a
x<>y n n I a a
RDN n I a a n
10^x I V a a n With the new code you have: L X Y Z T
+ ! v i a n n
R^ (rollup) v n i a n
 ! v I a n n
10^x ! I V a n n where:
a  your nunmber
n  digit to extract
I  intermediate index
V  digit position
If you want to preserve a copy of the original number (a), you can use this version (same length): *LBL L !
ENTER !
LOG !
IP !
2 !
R^ (rollup)
 !
+ !
10^x !
/ !
FP !
10 !
* !
IP !
RTN
Hope this helps.
Luiz (Brazil)
Edited: 22 Nov 2005, 4:06 p.m.
▼
Posts: 1,830
Threads: 113
Joined: Aug 2005
Very cool, Luiz!
I figured there were better ways to do the stack manipulations, and this fits the bill perfectly. I have quite a ways to go to get it all to fit into 224 steps on the 97, but if I can milk more code for a line here and there, I might just make it. First I'm going to finish with the 33S version, to get a concrete target to shoot at.
Thanks!
Regards, Howard
▼
Posts: 4,027
Threads: 172
Joined: Aug 2005
Hi, Howard;
I know what you mean, believe me. I'm actually having some good experiences with sqweezing some original TI59 programs to the HP67/97. I had to virtually 'crack the code' in some pieces, but one of the main achievements of mine was a couple of months ago, when I could generate an equivalent HP97 code with 3 parts (three mag cards) from an original TI59 also threeparts program. The fact is that the three HP97 parts together are a bit bigger than one of the three original TI59 parts. And it works perfectly fine...
Success!
Luiz (Brazil)
Posts: 1,755
Threads: 112
Joined: Jan 2005
Hi, Howard:
If you ever decide to port your YATZ program to the HP71B, this does the trick:
VAL(STR$(N)[P,P])
where N is your number and P is the desired digit's position.
So, for instance, if N is 3141592654 you would have:
VAL(STR$(N)[1,1]) > 3, the digit at the 1st position
VAL(STR$(N)[3,3]) > 4, the digit at the 3rd position
and so on. Also, should you decide to port your game to the HP15C, these steps will do:
STO RAN#
X<>Y
10^X
RCL RAN#
*
FRAC
10
*
INT
assuming the digit positions are counted this way, for example for 3141592654:
digit position 0 1 2 3 4 5 6 7 8 9
orig. number 3 1 4 1 5 9 2 6 5 4
so, with the desired position in Y and the orig. number in X, executing the above steps would do the following (say you want the digit at position 6):
T: T T: Z
Z: Z > Z: Z
Y: 6 Y: 3141592654
X: 3141592654 X: 2
so your original number is preserved intact in Y, the desired digit is of course in X, plus the original contents of Z are preserved as well.
If you want to count digit positions starting at 1 instead of 0, simply subtract 1 from Y after the X<>Y. The routine is quite fast as it uses no LOG instructions, just a single, integerargument 10^X, and would be even shorter if the HP15C had either the SIGN or the MOD (or RMD, remainder) functions builtin, which, alas, it doesn't ... nobody's perfect.
BTW, I have no HP15C at hand right now, but believe the above steps are correct.
Best regards from V.
Edited: 23 Nov 2005, 7:11 a.m.
▼
Posts: 464
Threads: 10
Joined: Jan 2005
Hi Valentin,
Maybe I missed something but Howard's YATZ IS a 71B program :)
Regards
Etienne
▼
Posts: 1,755
Threads: 112
Joined: Jan 2005
Hi, Etienne:
I've read this whole thread again and didn't find any
reference to the 71B except my own ... how could
I know it was originally written for the 71B !?
Best regards from V.
Posts: 1,830
Threads: 113
Joined: Aug 2005
Yes, the 71B version was the first one I did. But it doesn't use the same approach to encoding the dice as digits in a five digit number. Since the BASIC has arrays, I just used those. The "grand tour" is a project to implement the Yahtzee dice game on all of the programmable platforms in my collection, or on as many as I can. Each version will try to take advantage of the features, and work within the constraints of the particular platform. The point of the exercise is to familarize (or refamilarize) myself with programming on each of the platforms in question. I also intend to write about each implementation, giving my personal history with the particular machine, as well as any unique challenges or features that interest me. So far I've done the 71B and the 9816, both in BASIC.
The encoding scheme used here comes from the original program, which is not my software. It's a 41C program that I thought was either here or on TOS, but I can't locate it either place at the moment. I haven't studied the source, but I've played the game quite a bit. It shows the dice as a string of five digits, sorted in ascending order lefttoright. The user enters another number consisting of digit positions in the first string. This works pretty much as in Valentin's diagram, except the first (leftmost) digit is digit "1".
It bothers me that I can't locate the original HP41 program now. I have the program itself, so that's not a concern. But I really do need to attribute the original program as well as I can to the original source.
Posts: 1,830
Threads: 113
Joined: Aug 2005
STO RAN#
X<>Y
10^X
RCL RAN#
*
FRAC
10
*
INT
Devilishly clever! I suppose I shouldn't have expected less from you. 8)
From the HP15C manual, page 48:
Quote:
STO f RAN# will store the Xregister number (0<=r<1) as a new seed for the random number generator. (A value for r outside this range will be converted to fit within the range.)
Italics are mine.
The manual doesn't say how the number is "converted" but testing shows it takes place in the most straightforward way: the number is scaled down to be less than 1 by dividing it appropriately by powers of ten. Thus we have a microcoded operator that replaces the logarithm and division, and some stack manipulaton. Presumably this is much faster, though I haven't timed it.
Since the game needs a "onebase" specifier, the above code needs to add a "1 " before the "10^X" but that hardly detracts from the suprise nature of the solution!
Thanks, Valentin! I hadn't considered the 15C a suitable platform for this exercise, but with more tricks like that, I may well give it a try!
Regards, Howard
Edited: 23 Nov 2005, 3:42 p.m.
▼
Posts: 1,755
Threads: 112
Joined: Jan 2005
Hi, Howard:
Howard wrote:
"Devilishly clever! I suppose I shouldn't have expected less from you. 8)"
Thanks, I'm blushing ... :)
"Thus we have a microcoded operator that replaces the logarithm and division, and some stack manipulaton. Presumably this is much faster, though I haven't timed it."
It is, indeed. Virtually instantaneous apart from the time it takes to decode and execute the program step itself (i.e.: it takes almost the same time as a true NOP). I guess that, internally, it just strips the number off from everything but the mantissa proper, thus getting rid of the exponent without divisions or other timeconsuming operations.
" Thanks, Valentin! I hadn't considered the 15C a suitable platform for this exercise, but with more tricks like that, I may well give it a try!"
You should. The HP15C has many times over the programming capabilities of an HP67/97, and, apart from the 41C and its synthetic programming, it's HP's most trickridden calc ! If in doubt, search the archives for my "HP15 minichallenges", to see how its many advanced functions can be cleverly used to optimize programs and routines to astonishing degrees. A YATZ program for it could be made into a work of art, no less.
By the way, I think I own a copy of the original YATZ program from HP User's Library. I'll try and locate it and will tell you the original author, if you still want to know.
Best regards from V.
▼
Posts: 1,830
Threads: 113
Joined: Aug 2005
Quote:
The HP15C has many times over the programming capabilities of an HP67/97, and, apart from the 41C and its synthetic programming, it's HP's most trickridden calc !
Well, 338 bytes of memory, assuming most instructions are one byte, together with the ability to have duplicate forwardbranch labels, ought to allow me to implement the game of the 15C. Whether it will be a "work of art" remains to be seen. 8)
Quote:
By the way, I think I own a copy of the original YATZ program from HP User's Library. I'll try and locate it and will tell you the original author, if you still want to know
That rings a bell. But I don't find the game in my collection of User Library programs. There is no 41C program in the swap disks beginning with "Y," other than one named "Y," which isn't the one. So I must have picked it up online somewhere. But I don't see it here or on TOS.
Please do let me know the original author's name and the User Library number, if you get a chance, Valentin. Thanks!
Regards, Howard
Edited: 25 Nov 2005, 5:03 p.m.
Posts: 68
Threads: 1
Joined: Jul 2005
Hi Howard,
You would need to see how this suggestion would affect the rest of your program, but if it is possible to change the way you store numbers so that you can end up having to extract the n'th digit counting right to left, instead of from left to right, then you could use the following:
L0001 LBL L
L0002 x<>y
L0003 10^x
L0004 /
L0005 FP
L0006 10
L0007 *
L0008 IP
L0009 RTN
As an example, if Y contains 3 and X contains 1234567, then this routine will return 5.
Additionally, if it is possible to have the digit to be extracted in the X register and the original number in the Y register, then the x<>y on line 2 can be removed, saving another step in this function. Again, you would have to evaluate how this may or may not impact the rest of your program.
Best Regards,
Eamonn.
▼
Posts: 3,283
Threads: 104
Joined: Jul 2005
I understand that the original number has always 5 digits. If that's true, it's a waste to create a routine that can cope with aribtrarily long numbers. If you can't count from right (because it's the user that enters the digit positions and you do not want to change the user interface), just subtract the digit postion from 6.
L0001 LBL L
L0002 x<>y
L0003 6
L0004 
L0005 10^x
L0006 *
L0007 FP
L0008 10
L0009 *
L0010 IP
L0011 RTN
Because of the sign change, the step L0006 (was L0004) now is * instead of /.
Marcus
▼
Posts: 1,830
Threads: 113
Joined: Aug 2005
Unfortunately, I need the generality because the user inputs a string of digits representing the "dice" to throw away in the five digit number. For example, if I had "22345" and I wanted to try for the twos, I would enter "354" (or any permutation) to throw away the "345" in the five digit string. If I wanted to try to turn the small straight into a large straight, I would enter "1" or "2" to throw away one of the twos. So the input number can be from 0 to 5 digits (0 is a special case meaning "score now") and it can have the "throwaway" digit positions in any order.
▼
Posts: 3,283
Threads: 104
Joined: Jul 2005
Howard,
in this case, you can simply parse the string from the right. You'll get one digit after the other until the number is zero.
Marcus
▼
Posts: 1,830
Threads: 113
Joined: Aug 2005
Ah, but I want to avoid using a label, too, if I can. Especially on the 33S, where all labels are global. On the 97, I can branch forward to a label that can be repeated elsewhere. But a loop that will process any number of digits, up to five, requires a backward branch. On the 33S, I could unroll the loop, trading labels for lines. I'd have to set a flag and return on that to avoid a forward branch there. But trading lines for labels is not an option on the 97. There I'm already running into the line limit.
So what I need is code that uses few lines and no labels. So far, Luiz has the best code that fits the bill on the 33S, and also the 97. Valentin's trick of using the random seed initialization on the 15C is the overall winner, but it only works on the 15C.
