This is a follow up on an archived message:
http://www.hpmuseum.org/cgisys/cgiwrap/hpmuseum/archv015.cgi?read=72151
I've ported my algorithm to my trusty TI95 PROCALC, a machine I baught when they still were in the shops.
If you own the PCInterface, you can compile the source with TIC95.EXE and load it into your calc.
The program presents a menu with 4 selections:
F1:GO Run the loop
F2:TST Run a single test on one number, displays the smallest digit.
F3:DIG Set number of different digits (2 or 3), 2 is default
F4:BEG Set beginning of loop, default is 33334.
For F3/F4, you have to enter the number and then press the key.
The most interesting result for me was that the TI95 is noticably faster than my HP 42 (some 10 to 20% percieved).
The algorithm is essentially the same. The programming model in both calcs is comparable. TI's comparison statements work against registers (no longer the "t" register only). In many cases I had to store a value in a register on the TI where I could use the stack on the HP. Registers can be accessed by letters but this is just a shorthand notation to the corresponding numbers (RCL 000 is the same as RCL A).
The flags are used just the opposite way in my HP implementation and in this program: On the HP, I reset a flag when a corresponding digit is found while I set a flag on the TI. The reason is simple: the HP has a FC?C instruction that tests and clears a flag in one step. The feature is missing on the TI so I could use the more natural approach of setting the flags instead or clearing them.
Another missing feature on the TI is MOD: I had to use a more complicated formula to get the last digit.
Some statements can only be entered in so called unprotected (system) mode. These are SBA 226, a call to an assembly routine which does a VIEW (not available on the keyboard), and STB 00xx, which stores a byte in memory. The latter is used to clear the flags.
After entering the program you can speed it up with the ASM key: it replaces all (slow) label jumps by absolute jumps. INV ASM undoes the change.
Here is the program:
'
' Find 10 digit squares with at most 2 or 3 different digits
'
DFN CLR
DFN F1:GO @GO ' Start computation
DFN F2:TST@TT ' Test a single value
DFN F3:DIG@DD ' Set # of different digits (2, 3)
DFN F4:BEG@BB ' Set first guess
2
SBL DD ' Default: 2 different digits
33334
SBL BB ' First guess to square & test
CLR
HLTLBL AA ' check a value against # of digits
INC H ' some statistics
SBA 226 ' display without delay
STO A ' scratch register for value
0
STB 0028 ' system register: Flags 07
STB 0029 ' system register: Flags 815
STO C ' clear # of digits found so far
LBL A1
( ' compute A MOD 10 and INT( A / 10 )
RCL A

(
/
1
0
)
INT
STO A ' this is INT( A / 10 )
*
10
) ' this is A MOD 10 (last digit of number)
STO B ' use B for indirect flag setting
INV TF IND B
INC C ' digit not yet encounterd, count it
SF IND B ' mark digit
RCL C ' get count
IF> D ' compare to maximum digits
SF 00 ' too many digits
TF 00 ' tested number has failed
RTN ' (0 encountered or too many digits)
0 ' all digits tested?
IF= A
RTN ' done
GTL A1 ' next digitLBL CC ' get smallest valid digit for next guess
RCL C ' # of digits found
IF= D ' is the allowed maximum?
GTL C1 ' find the smallest digit encounterd
1 ' not all allowed digits in last try
RTN ' must return 1
LBL C1
1 ' digit index starts with 1
STO B
LBL C2
TF IND B ' is digit in last tested number?
RTN ' yes, must be the smallest
INC B ' next digit
RCL B ' get it (in case of return)
GTL C2 ' loopLBL DD ' store # of allowed digits (key F3)
STO D
RTNLBL BB ' store first number to square
STO E ' compensate for INC E in main loop
INV INC E
0 ' initialize counters and comparison values
STO F ' first 4 digits
STO G ' first 3 digits
STO H ' total # of checks
RTNLBL GO ' main loop starts here (key F1)
INC E ' next # to square
99999 ' check end of loop
INV IF> E
GTL ZZ ' done
( ' compute first 4 digits of squared #
RCL E
x^2
/
1000000
)
INT
INV IF= F ' same 4 digits as last try?
SBL FF ' no, get next guess based on first 4 digits
RCL E ' get number again
x^2 ' and square it
SBL AA ' digit test routine
INV TF 00 ' check it test passed
SBL PR ' got it, show/print result
GTL GO ' next guessLBL FF ' find a new guess based on first 4 digits
STO F
LBL F1
RCL F ' 4 digits to test
( ' check if first 3 digits have changed
/
10
)
INT
INV IF= G
SBL GG ' check first 3 digits first
RCL F ' get current guess
SBL AA ' test it
INV TF 00
GTL F2 ' test passed: compute new guess for main loop
INC F ' test failed, try next 4 digit number
GTL F1
LBL F2 ' compute a new guess
(
(
RCL F ' first 4
*
10 ' shifted 1 left
+
SBL CC ' add smallest possible next digit
)
*
100000 ' shift 5 left
+
11110 ' offset which can be added safely
)
SQR ' the INT of the square root is next guess
INT
STO E ' store it
INC E ' our guess was still too small
RTNLBL GG ' find a new guess based on first 3 digits
STO G ' 3 digits to test
LBL G1
RCL G ' get current guess
SBL AA ' test it
INV TF 00
GTL G2 ' test passed: compute new guess for FF loop
INC G ' test failed, try next 3 digit number
GTL G1
LBL G2 ' compute a new guess
(
RCL G ' first 3
*
10 ' shifted 1 left
+
SBL CC ' add smallest possible next digit
)
STO F ' store it
RTNLBL PR ' print or show a valid result
RCL E ' number to be squared
PRT
x~t ' save in tRegister
RCL E
x^2 ' squared number in display
PRT
INV TF 74
BRK ' halt if no printer connected
RCL C ' number of different digits
PRT
( ' flag word
RCB 0028
+
RCB 0029
*
256
)
HEX ' print it in HEX
PRT
DEC ' revert to normal display
RTNLBL TT ' test a single value (key F2)
SBL AA ' call test routine
0
TF 00
HLT ' stop and show 0 if test failed
SBL CC ' show smallest digit or 1 if less then
HLT ' the allowed number were foundLBL ZZ ' end of main loop
RCL H ' show number of checks
PRT
HLT
END