The Museum of HP Calculators

HP Forum Archive 17

HP42S Mini-Challenge: Optimizing !
Message #1 Posted by Valentin Albillo on 1 May 2007, 10:57 p.m.

Hi all,

A new month's just begun and a little, HP42S-specific Mini-Challenge might prove an adequate welcome for it and a nice ocassion to flex your HP42S programming muscles. So this is

## The Mini-Challenge

We say that a positive integer is palindromic if it reads the same forwards and backwards, such as 1771 or 32823. Some integer squares can also be palindromic, such as 121 = 112.

There is one and only one 12-digit palindromic square and you must write an HP42S program to try and find it, your choice(s) among three possible flavours:

1. Optimized for minimum size, regardless of speed

2. Optimized primarily for speed, secondarily for size

3. Optimized for maximum speed

Some notes:

• The goal for (1) is to achive the smallest possible program, even if it would take extremely long to find the unique answer.

• The goal for (2) is to find the answer as quick as possible but with some concern as to program size and reasonably "elegant" code.

• The goal for (3) is to find the answer as fast as possible, even at the expense of longer or not-so-elegant code.

• Both (2) and (3) must be able to find the solution in a physical HP42S in a few hours at most.

Your program must stop as soon as it finds the unique answer (no need to search for more) and the usual caveats apply, namely:

• Avoid googling for the answer, any moron can do that and it would be extremely lame. The idea is to work it out and show some programming muscle and good, worthwhile ideas which might be useful for other tasks. If you can't solve this on your own, you aren't worth your salt as an HP-calc programmer.

• Using reasonable, sound heuristics which can be rationalized in a few words is Ok and recommended, but avoid doing all the theoretical work yourself with paper and pen, then have the program simply print the answer after looking at a handful cases. The idea is for the machine to do the bulk of the work, not you.

• This mini-challenge is HP42S-specific in the sense that I'll post my original solutions which are HP42S RPN programs using some neat tricks that are indeed HP42S-specific. It would be nice if you would write HP42S programs too, you can always use some good emulator (Emu42 or Free42, for instance) if you don't have a physical HP42S.

That failing, you may nevertheless use any 12-digit HP calc model and see what you come up with.

I'll post my original solutions for the HP42S within a few days, as always, which, as a guide to measure your efforts, have the following characteristics:

1. Trivial but takes ages

2. 72 steps (157-byte), R00-R11 used, finds the unique solution in 2 h 42 min in a physical HP42S, 85 seconds in Emu42 @ 2.4 Ghz, 44 seconds in Free42 @ Palm Z100

3. 129 steps (239-byte), R00-R11 used, finds the unique solution in 1 h 48 min in a physical HP42S, 56 seconds in Emu42 @ 2.4 Ghz, 29 seconds in Free42 @ Palm Z100

Enjoy ! :-)

Best regards from V.

 Re: HP42S Mini-Challenge: Optimizing !Message #2 Posted by Egan Ford on 2 May 2007, 12:31 p.m.,in response to message #1 by Valentin Albillo Thanks for this challenge. My 42S has been collecting dust since I use my 15C, 71B, and 50G for challenges. Here is my first min size entry. I didn't have a lot of time to work on it. I know there is room for improvement. This is a brute force search starting at 999999 and working down. Once squared a decimal point is used to separate the 2 halves. The right half is flipped and subtracted from the left half. If the result = 0, then you have found it. 40 steps, 66 bytes. Free42 on my notebook breezed through this in about 40 seconds. ETA for physical 42S: 95-96 hours. I do not have any EMU42 timings. I am too lazy to dump my 42S ROM to my 48GX so that I can use EMU42. I hate to ask this, but can someone please email a ROM dump (I can provide proof that I own a 42S if necessary). This does not use any unique feature of the 42S so it should be portable to other models (e.g. 15C, however you'll have to settle for a 9 digit palindromic square, there is no 10).  1 LBL "PP" 2 1E6 3 STO 00 4 LBL A 5 1 6 STO- 00 7 6 8 STO 03 9 0 10 STO 02 11 RCL 00 12 X^2 13 1E6 14 / 15 FP 16 LASTX 17 IP 18 STO 01 19 LBL B 20 X<>Y 21 10 22 x 23 FP 24 LASTX 25 IP 26 6 27 RCL 03 28 - 29 10^X 30 x 31 STO+ 02 32 DSE 03 33 GTO B 34 RCL 01 35 RCL 02 36 - 37 X!=0? 38 GTO A 39 RCL 00 40 X^2 

 Re: HP42S Mini-Challenge: Optimizing !Message #3 Posted by Paul Dale on 2 May 2007, 5:44 p.m.,in response to message #1 by Valentin Albillo [edit: added solution time] Interesting challenge as usual. I cannot think of a "clever/short" method to do the palindrome generation on a 42S, however I did some up with this fragment on the HP49g+:  ->STR DUP SREV ==  You'll need to attach library 256 for the SREV to be resolved properly (i.e. 256 ATTACH before entering the above fragment. You'll also want everything to stay integer (i.e. not approximate mode). A final program that performs the search:  << 6 ALOG 10^x WHILE 1. REPEAT 1 - DUP SQ x^2 ->STR DUP SREV == << HALT >> IFT END >>  70.5 bytes, checksum #AF30h Running time is a couple of minutes under an hour for an agumented version that inserted a TICKS before the HALT. - Pauli Edited: 2 May 2007, 7:32 p.m.

 Re: HP42S Mini-Challenge: Optimizing !Message #4 Posted by hugh steers on 2 May 2007, 6:17 p.m.,in response to message #1 by Valentin Albillo hi valentin, i started wondering if the so-called "196" algorithm was a good way to search for palindromes of a given size. 196 algorithm: given a number, reverse its digits, add to original number. repeat process until palindromic (or give up after too big). i figure that since your number is unique, unless the 196 can't hit a 12 digit number, it will find it by chance fairly quickly. sure enough i get it after putting in 899. so it took me 799 trials (started at 100). end of the output looks like this: 870 8836886388 871 15851 872 1661 873 2772 874 3883 875 4994 876 23232 877 47674 878 878 879 0 880 0 881 233332 882 1881 883 2992 884 7117 885 9339 886 1136311 887 0 888 888 889 881188 890 881188 891 79497 892 3113 893 5335 894 7557 895 9779 896 22022 897 46464 898 898 899 133697796331 woot!  not sure if this would make a good approach for a 42 program. probably not.

 Re: HP42S Mini-Challenge: Optimizing !Message #5 Posted by Paul Dale on 2 May 2007, 6:26 p.m.,in response to message #4 by hugh steers Quote: 899 133697796331  I'm not sure you're on the right track here. You've found a 12 digit palindrome but 133697796331 is not a square number. Palindromes of this size are very easy to find, choose any six digit number not ending with a zero reverse the digits and prepend. Finding the unique one which is also a square is harder. - Pauli

 Re: HP42S Mini-Challenge: Optimizing !Message #6 Posted by Egan Ford on 2 May 2007, 10:46 p.m.,in response to message #1 by Valentin Albillo My first attempt at fast. I have not tested on real 42S yet, but with Free42 it runs in about 10 sec. This differs from my brute force attempt in a number of ways. Instead of calculating squares with X^2, squares are calculated by subtracting odd numbers. (A perfect square N^2 is = to the sum of the first N odds). By using the squares I can cut the numbers of searches by half because perfect squares cannot end in 8,7,3 or 2. I can also skip 0 since palindromic numbers do not start with 0. So I only check numbers starting with 9,6,5,4 and 1. There is no need to check every square, only check the squares ending with the starting number. I can determine the next square with that matches the lead digit by multiplying the next square deference by 10 and subtracting 90. This has to be done twice because there are two patterns of matching digits spaced 10 squares apart. This reduces the number of searches by 4/5ths. (A simple mod 10 check may be faster). Overall the total number of iterations required vs. brute force is 1/10. To further increase performance the check for palindromic exits early if any number does not match (brute force checked all digits). Loop unrolling also helps. This part needs more help. Like my earlier post this is not 42S specific. I'll include my Perl prototype, it is easier to read. 1 LBL "PP2" 2 9 3 0 4 XEQ B 5 9 6 1 7 XEQ B 8 6 9 0 10 XEQ B 11 6 12 1 13 XEQ B 14 5 15 0 16 XEQ B 17 5 18 1 19 XEQ B 20 4 21 0 22 XEQ B 23 4 24 1 25 XEQ B 26 1 27 0 28 XEQ B 29 1 30 1 31 XEQ B 32 LBL B 33 STO 04 34 X<>Y 35 STO 03 36 1 37 + 38 11 39 10^X 40 x 41 1 42 - 43 SQRT 44 IP 45 X^2 46 STO 05 47 LASTX 48 1 49 - 50 X^2 51 - 52 STO 06 53 LBL 00 54 RCL 05 55 10 56 MOD 57 RCL 03 58 X=Y? 59 GTO 01 60 RCL 06 61 STO- 05 62 2 63 STO- 06 64 GTO 00 65 LBL 01 66 RCL 04 67 X=0? 68 GTO 02 69 0 70 STO 04 71 RCL 06 72 STO- 05 73 2 74 STO- 06 75 GTO 00 76 LBL 02 77 RCL 03 78 11 79 10^X 80 * 81 STO 07 82 LBL 04 83 RCL 07 84 RCL 05 85 XY 94 STO 01 95 10 96 MOD 97 10 98 RCLx 02 99 IP 100 X!=Y? 101 GTO 03 102 1E-1 103 RCLx 01 104 IP 105 10 106 MOD 107 10 108 RCLx 02 109 FP 110 10 111 x 112 IP 113 X!=Y? 114 GTO 03 115 1E-2 116 RCLx 01 117 IP 118 10 119 MOD 120 1E2 121 RCLx 02 122 FP 123 10 124 x 125 IP 126 X!=Y? 127 GTO 03 128 1E-3 129 RCLx 01 130 IP 131 10 132 MOD 133 1E3 134 RCLx 02 135 FP 136 10 137 x 138 IP 139 X!=Y? 140 GTO 03 141 1E-4 142 RCLx 01 143 IP 144 10 145 MOD 146 1E4 147 RCLx 02 148 FP 149 10 150 x 151 IP 152 X!=Y? 153 GTO 03 154 1E-5 155 RCLx 01 156 IP 157 10 158 MOD 159 1E5 160 RCLx 02 161 FP 162 10 163 x 164 IP 165 X!=Y? 166 GTO 03 167 GTO E 168 LBL 03 169 10 170 RCLx 06 171 90 172 - 173 STO- 05 174 20 175 STO- 06 176 GTO 02 177 LBL E 178 RCL 05 179 STOP  #!/usr/bin/perl $lc=0; print "9...\n"; a(9,0); a(9,1); print "6...\n"; a(6,0); a(6,1); #will not get here; a(5,0); a(5,1); a(4,0); a(4,1); a(1,0); a(1,1); sub a { my$leaddigit = shift; my $nexthigh = shift; my$highnum = ($leaddigit + 1) * 10**11 - 1; my$highsqrt = int(sqrt($highnum)); my$nexthighsqrt = $highsqrt - 1; my$highsqr = $highsqrt**2; my$odd = $highsqr -$nexthighsqrt**2; while($highsqr % 10 !=$leaddigit) { $highsqr -=$odd; $odd -= 2; } if($nexthigh) { $highsqr -=$odd; $odd -= 2; while($highsqr % 10 != $leaddigit) {$highsqr -= $odd;$odd -= 2; } } while($highsqr >$leaddigit*10**11) { $lc++; my$a = $highsqr; my$left = int($a / 1e6); my$right = $a - int($a / 1e6) * 1e6; if($left - reverse($right) == 0) { $s =$a**.5; print $s . "\t" .$a . "\n"; print "loops:\t" . $lc . "\n"; exit(0); }$highsqr -= $odd * 10 - 90;$odd -= 20; } }  Edited: 3 May 2007, 2:44 a.m.

 Re: HP42S Mini-Challenge: Optimizing ! (Doh! Bug!)Message #7 Posted by Egan Ford on 4 May 2007, 12:55 a.m.,in response to message #6 by Egan Ford Line 80 above: 80 *  Should be 80 x  txt2raw.pl will ignore the *. The above takes 10 times longer than it should. Below is a fixed version with a few other cleanups. Still not 42S specific. Run times: Free42 @ 1.7 GHz Pentium M: 1 sec Emu42 @ 1.7 GHz Pentium M: 60 sec Free42 @ 471 MHz PXA255: 70 sec  I'll key this in my 42S and report the time this weekend. 00 { 343-Byte Prgm } 01>LBL "PP4" 02 9 03 0 04 XEQ B 05 9 06 1 07 XEQ B 08 6 09 0 10 XEQ B 11 6 12 1 13 XEQ B 14 5 15 0 16 XEQ B 17 5 18 1 19 XEQ B 20 4 21 0 22 XEQ B 23 4 24 1 25 XEQ B 26 1 27 0 28 XEQ B 29 1 30 1 31>LBL B 32 STO 04 33 X<>Y 34 STO 03 35 1 36 + 37 11 38 10^X 39 × 40 1 41 - 42 SQRT 43 IP 44 X^2 45 STO 05 46 LASTX 47 1 48 - 49 X^2 50 - 51 STO 06 52>LBL 00 53 RCL 05 54 10 55 MOD 56 RCL 03 57 X=Y? 58 GTO 01 59 RCL 06 60 STO- 05 61 2 62 STO- 06 63 GTO 00 64>LBL 01 65 RCL 04 66 X=0? 67 GTO 02 68 0 69 STO 04 70 RCL 06 71 STO- 05 72 2 73 STO- 06 74 GTO 00 75>LBL 02 76 11 77 10^X 78 RCL× 03 79 STO 07 80 GTO 04 81>LBL 03 82 10 83 RCL× 06 84 90 85 - 86 STO- 05 87 20 88 STO- 06 89>LBL 04 90 RCL 07 91 RCL 05 92 XY 101 STO 01 102 10 103 MOD 104 10 105 RCL× 02 106 IP 107 X!=Y? 108 GTO 03 109 0.1 110 RCL× 01 111 IP 112 10 113 MOD 114 10 115 RCL× 02 116 FP 117 10 118 × 119 IP 120 X!=Y? 121 GTO 03 122 0.01 123 RCL× 01 124 IP 125 10 126 MOD 127 100 128 RCL× 02 129 FP 130 10 131 × 132 IP 133 X!=Y? 134 GTO 03 135 1E-3 136 RCL× 01 137 IP 138 10 139 MOD 140 1E3 141 RCL× 02 142 FP 143 10 144 × 145 IP 146 X!=Y? 147 GTO 03 148 1E-4 149 RCL× 01 150 IP 151 10 152 MOD 153 1E4 154 RCL× 02 155 FP 156 10 157 × 158 IP 159 X!=Y? 160 GTO 03 161 1E-5 162 RCL× 01 163 IP 164 10 165 MOD 166 1E5 167 RCL× 02 168 FP 169 10 170 × 171 IP 172 X!=Y? 173 GTO 03 174 RCL 05 175 ENTER 176 SQRT 177 STOP 178 .END. 

 Re: HP42S Mini-Challenge: Optimizing !Message #8 Posted by J-F Garnier on 3 May 2007, 3:11 p.m.,in response to message #1 by Valentin Albillo Well, here is my solution for the HP-42S: 00 { 156-Byte Prgm } 01>LBL "PAL12" 02 FIX 00 03 CF 29 04 1E11 05 STO 00 06 1 07 1 08 XEQ A 09 9 10 1 11 XEQ A 12 2 13 4 14 XEQ A 15 8 16 4 17 XEQ A 18 5 19 5 20 XEQ A 21 4 22 6 23 XEQ A 24 6 25 6 26 XEQ A 27 3 28 9 29 XEQ A 30 7 31 9 32 XEQ A 33 RTN 34>LBL A 35 RCL ST X 36 1 37 + 38 RCL× 00 39 SQRT 40 STO 02 41 Rv 42 RCL× 00 43 SQRT 44 IP 45 RCL ST X 46 10 47 MOD 48 - 49 + 50 STO 01 51>LBL 00 52 X^2 53 XEQ 01 54 RCL 02 55 RCL 01 56 10 57 + 58 STO 01 59 XLBL 01 63 CLA 64 ARCL ST X 65 6 66 STO ST L 67>LBL 02 68 -1 69 AROT 70 ATOX 71 ATOX 72 X!=Y? 73 RTN 74 DSE ST L 75 GTO 02 76 RCL 01 77 X^2 78 VIEW ST X 79 STOP 80 RTN  And the HP-71B version, for free: 10 ! find 12-digit square palindrome 20 T=TIME 30 N=100000000000 ! 1E11 40 ! squares ending with '1', try numbers ending with '1' or '9' 50 K=1 @ R=1 @ GOSUB 150 @ R=9 @ GOSUB 150 60 ! squares ending with '4', try numbers ending with '2' or '8' 70 K=4 @ R=2 @ GOSUB 150 @ R=8 @ GOSUB 150 80 ! squares ending with '5', try numbers ending with '5' 90 K=5 @ R=5 @ GOSUB 150 100 ! squares ending with '6', try numbers ending with '4' or '6' 110 K=6 @ R=4 @ GOSUB 150 @ R=6 @ GOSUB 150 120 ! squares ending with '9', try numbers ending with '3' or '7' 130 K=9 @ R=3 @ GOSUB 150 @ R=7 @ GOSUB 150 140 END 150 A=(SQR(N*K) DIV 10)*10+R @ B=SQR(N*(K+1)) 160 FOR I=A TO B STEP 10 170 A$=STR$(I*I) 180 IF A$=REV$(A$) THEN DISP I;A$;TIME-T @ PAUSE 190 NEXT I 200 RETURN  May I add that these programs can be slightly modified to find the only one 8-digit hexadecimal palindromic square? J-F

 Re: HP42S Mini-Challenge: Optimizing !Message #9 Posted by Alex L on 3 May 2007, 3:23 p.m.,in response to message #1 by Valentin Albillo This is my first-ever submission to one of these challenges. I was aiming at part (1), but mostly just learning how to program my 42S. 41-byte, 25-step program, at the end displays both the base number in Y and the sought square in X. Uses only R01 and ALPHA. Fairly 42S-specific, I think, as it depends on the existence of a 12-digit integer representation to move into the ALPHA register with AIP. I had started counting up from 316228, but then realized that I could save 3 bytes in step 01 by counting down from 1E6. Turns out to save execution time, too. 18s on Free42 @ 2.1GHz, and based on two partial runs, an estimated 11h25m on a physical 42S. Since I'm an HP calculator programming rookie, I'd guess someone on this forum can make this algorithm even shorter. 01 1E6 02 STO 01 03 LBL 01 04 1 05 STO- 01 06 RCL 01 07 X^2 08 CLA 09 AIP 10 LBL 02 11 ALENG 12 2 13 X>Y? 14 GTO 03 15 -1 16 AROT 17 ATOX 18 ATOX 19 X=Y? 20 GTO 02 21 GTO 01 22 LBL 03 23 RCL 01 24 ENTER 25 X^2  Edited: 3 May 2007, 3:28 p.m.

 Re: HP42S Mini-Challenge: Optimizing !Message #10 Posted by Karl Schneider on 4 May 2007, 12:18 a.m.,in response to message #9 by Alex L Hello, Alex -- Quote: This is my first-ever submission to one of these challenges. I was aiming at part (1), but mostly just learning how to program my 42S. Well, I'm very impressed with your elegant program. I believe that you've taken the approach that Valentin had in mind, and which I didn't quite see how to do, having not researched all available HP-42S string commands. Quote: Fairly 42S-specific, I think, as it depends on the existence of a 12-digit integer representation to move into the ALPHA register with AIP. AIP (or J-F Garnier's "ARCL ST X") is indeed the key to making this approach work. If I were to tackle this problem with a C-language program, I would use "sprintf" or a non-standard library routine "itoa" to convert an integer to a string, then compared pairs of digits, working from the outside inward. I thought that the HP-42S "ATOX" and "XTOA" would be analogous, but they weren't. However, ATOX in conjunction with AIP and AROT was just the ticket. I've taken a similar approach, using numerical calculations instead of string operations to extract and remove the first and last digits of N2. It's slower and more cumbersome. Quote: I'd guess someone on this forum can make this algorithm even shorter. I don't see any particular way to make your algorithm much more concise, but the execution speed could be improved by using some basic heuristics that restrict, within appropriate ranges of N, which last-digit values of N2 to even check for. Good job! -- KS Edited: 4 May 2007, 12:52 a.m.

 Re: HP42S Mini-Challenge: Optimizing !Message #11 Posted by Alex L on 4 May 2007, 11:16 a.m.,in response to message #10 by Karl Schneider Karl, Quote: Well, I'm very impressed with your elegant program. ... Good job! Thank you! I'm especially happy with the generality of this algorithm. If you append 4 steps/6 bytes: 26 STOP 27 1 28 X!=Y? 29 GTO 01  then the program will display each palindromic square of 12 digits or fewer (36 in all, counting the trivially palindromic squares of 3, 2, and 1, only one other of which has an even number of digits). But it will take days on a physical 42S. Quote: the execution speed could be improved by using some basic heuristics that restrict, within appropriate ranges of N, which last-digit values of N2 to even check for I'm enjoying studying the other submissions to this challenge to see slick ways to do exactly that. -A

 Re: HP42S Mini-Challenge: Optimizing !Message #12 Posted by Allen on 9 May 2007, 9:22 p.m.,in response to message #10 by Karl Schneider Quote: I don't see any particular way to make your algorithm much more concise Karl, I am surprised that you made no comment RE the 32 byte solution or the X/11 heuristic I added below, the former being 25% smaller than the previous post. I really enjoy the 'write a small program' challenges. Also enjoy the heuristics you added. In both case 1 and 3 (but not Valentin's case #2-speed/size challenge) The creation of these algorithms is mathematical poetry! You and Alex are both great writers, among others here. Hats off to all.

 Some comments: HP42S Mini-ChallengeMessage #13 Posted by Karl Schneider on 10 May 2007, 12:58 a.m.,in response to message #12 by Allen Quote: Karl, I am surprised that you made no comment RE the 32 byte solution or the X/11 heuristic I added below,... Hi, Allen -- I did incorporate the X/11 heuristic into my own solution, which reduced the execution time by more than 60%. Paul Brogger had included it in his submission, prior to yours. I hadn't even known of the theorem until then. Your 32-byte program seemed to have the same basis as Alex' program. His algorithm was already taut, but there's always a way to save a few bytes... Quote: I really enjoy the 'write a small program' challenges. I don't, in particular. It seems to me that reduction of program size to its absolute minimum defeats the true purpose of a programmable calculator: To allow the user to quickly create functional programmed solutions to a problem without the need to remember syntactical rules, spellings, formalities, and compilation procedures. "Paring down" of a program may have been necessary for implementing anything non-trivial on the earliest programmables, but not on a HP-42S with 7 kB of RAM. -- KS Edited: 10 May 2007, 1:18 a.m.

 Re: HP42S Mini-Challenge: Optimizing !Message #14 Posted by Werner on 3 May 2007, 4:57 p.m.,in response to message #1 by Valentin Albillo I took the following approach: I generate the 12-digit palindromes, generating the first (and last) two digits separately making use of the knowledge that the number is a square (thus dividing the work by four, roughly), and just blind force for the inner loop. It is not HP-42 specific. timing: 1m13s @ 1.4Ghz size: 115 Bytes, regs R1-R5 used 00 { 115-Byte Prgm } 01*LBL "P12" 02 99 03 STO 05 04*LBL 05 generate xy00000000yx, with yx = R05^2 MOD 100 05 RCL 05 06 X^2 07 100 08 MOD 09 X=0? can't start/end with zeroes 10 GTO 99 11 10 12 STO 04 13 % 14 ENTER 15 FP 16 100 17 * 18 + 19 IP 20 1e10 21 * 22 + 23*LBL 04 24 10 25 STO 03 26 RDN 27*LBL 03 28 10 29 STO 02 30 RDN 31*LBL 02 32 10 33 STO 01 34 RDN 35*LBL 01 inner loop 36 ENTER test for square 37 SQRT 38 FP 39 X=0? 40 RTN 41 RDN 42 11e5 add 1 to innermost digits (6 and 7) 43 + 44 DSE 01 45 GTO 01 46 99e4 adjust for digits 5 and 8 47 - 48 DSE 02 49 GTO 02 50 99e3 adjust for digits 4 and 9 51 - 52 DSE 03 53 GTO 03 54 99e2 55 - 56 DSE 04 57 GTO 04 58*LBL 99 59 DSE 05 60 GTO 05 61 END 

 Re: HP42S Mini-Challenge: Optimizing !Message #15 Posted by Paul Brogger on 3 May 2007, 7:24 p.m.,in response to message #1 by Valentin Albillo I wrote mine originally on the HP-33s, then copied it to Free42 on Windows. As such, it doesn't make use of any particular HP-42s features, and so isn't optimized for that machine. It uses two registers, R00 and R01.  00 { 66-Byte Prgm } 01>LBL 00 02 99999 Iterate through all 6-digit first-halves, 03 STO 00 starting at 100,000 04>LBL 01 05 1 06 STO+ 00 Increment high-order six-digit section 07 0 08 RCL 00 Put it in x 09 XEQ 02 10 XEQ 02 Reverse 11 XEQ 02 12 XEQ 02 that 13 XEQ 02 14 XEQ 02 in y 15 Rv 16 RCL 00 and 17 1E6 splice 18 * them 19 + together 20 STO 01 (save 12-digit value, in case I need it later) 21 SQRT 22 FP 23 X!=0? Is it the square of some integer? 24 GTO 01 no -- try next 6-digit value 25 RCL 01 yes! -- stop with 12-digit palindromic square in x 26 STOP 27>LBL 02 28 10 Take low-order digit 29 ÷ in x, 30 FP 31 LASTX 32 IP 33 Rv 34 + and append it 35 10 to y, shifting that left 36 * 37 R^ 38 RTN  Pretty fast (~53 sec.) on Free42Decimal (on 2.8GHz Win2000) and very slow (still running) on HP-33s. (To use only one register, don't save in R01, and replace line 25 with a LASTx, x^2.) Edited: 3 May 2007, 10:44 p.m.

 Re: HP42S Mini-Challenge: Optimizing !Message #16 Posted by Paul Brogger on 4 May 2007, 2:30 a.m.,in response to message #15 by Paul Brogger This one takes about a third the time of my previous attempt. It has (if I do say so myself) a pretty slick test for palindromicity (?) in section labeled LBL 02.  00 { 58-Byte Prgm } 01>LBL 00 02 316227 03 STO 00 04>LBL 01 Increment integer 05 1 06 STO+ 00 07 RCL 00 08 X^2 and square it 09 1E6 10
prior to palindrome test. 11>LBL 02 Assumes decimal point in center of 12 X=0? even-length palindromic sequence in x. 13 GTO 03 If zero, we've found our result. 14 10 15 Shift one digit left 16 FP 17 LASTX 18 IP 19 100 Then two digits right 20
21 IP 22 LASTX 23 FP 24 0.11 Divide middle two digits by .11 25
26 FP 27 X!=0? 28 GTO 01 Don't match? Try square of next integer. 29 Rv 30 + Concatenate remaining fragments 31 GTO 02 and test next middle two digits 32>LBL 03 33 RCL 00 34 X^2 35 RTN  It uses only register R00. Edited: 9 May 2007, 5:33 p.m.

 Re: HP42S Mini-Challenge: Optimizing !Message #17 Posted by Gerson W. Barbosa on 3 May 2007, 9:18 p.m.,in response to message #1 by Valentin Albillo Hi Valentin, Quote: 1. Optimized for minimum size, regardless of speed It was not my intention to participate on this one, although it's very interesting as always. I would try goal one at most. Looks like I was able to optimize for minimum speed only :-) About 5 minutes (Free42 @ 500 MHz), which means about 46 hours on the real 42S. 00 { 64-Byte Prgm } 01>LBL "SP" 02 1E6 03 STO 09 04>LBL 01 05 1 06 STO- 09 07 6 08 STO 00 09 RCL 09 10 0 11 STO 08 12>LBL 00 13 X<>Y 14 IP 15 10 16 ÷ 17 ENTER 18 FP 19 RCL 00 20 10^X 21 × 22 STO+ 08 23 DSE 00 24 GTO 00 25 RCL 09 26 1E6 27 × 28 RCL 08 29 + 30 SQRT 31 FP 32 X!=0? 33 GTO 01 34 1E6 35 RCL× 09 36 RCL+ 08 37 .END.  Best regards, Gerson.

 Re: HP42S Mini-Challenge: Optimizing ! (final submission)Message #18 Posted by Egan Ford on 5 May 2007, 1:41 p.m.,in response to message #1 by Valentin Albillo Quote: Enjoy ! :-) I did. This is my final submission for part 3 (speed) of this mini challenge. One of my objectives from the start was to NOT be 42S specific (personal challenge). As for, "Using reasonable, sound heuristics which can be rationalized in a few words is Ok". I'll let you be the judge. Answer: 798,644 * 798,644 = 637,832,238,736  Runtimes: Free42, 1.7 GHz Pentium M: <1 sec Emu42, 1.7 GHz Pentium M: 23 sec Physical 42S: 1h, 2min  Code suitable for import into Free42 or Emu42: http://sense.net/~egan/pp9.txt.raw. I broke this problem down into two separate problems: iteration reduction and verification optimization. Iteration reduction: My initial brute force approach started at 999999 and counted down until a solution was found. I selected count down vs. count up because I was planning on using DSE (easier than ISE). This approach will make 201,355 attempts to find a solution. Heuristical methods will need to be used to reduce this. Knowing that perfect squares must end in 0, 1, 4, 5, 6, or 9, I opted to count down from the largest 12 digit square (999999^2) and ignore any that didn't start with 9, 6, 5, 4, or 1. This will cut the number of iterations roughly in half. 89,333 iterations to be exact. Since N*N = the sum of the first N odd numbers, counting down is easy. Just find the last odd: 999999*2 - 999998*2. Then subtract 2 from the odd in a loop to get the difference to the next perfect square. Of the perfect squares only a fraction will end in with a digit that matches the first. Is there a way to determine the next first/last matching digit perfect square? Yes, there is. Just sum 10 sequential odd numbers to get a result that ends in 0. Simply find the first perfect square with matching first/last digit by subtracting the odds, then to get 10 odds down, take the next odd, multiple by 10, subtract 90. This approach does have one gotcha, there are 2 series of first/last matching squares, and both have to be searched, e.g.: 999999^2 = 999998000001 <= Start at top. End in 9? No, then subtract odd difference. 999998^2 = 999996000004 <= End in 9? No, then subtract odd difference. 999997^2 = 999994000009 <= End in 9? Yes, 10*odd diff - 90 -------. 999996^2 = 999992000016 | 999995^2 = 999990000025 | 999994^2 = 999988000036 | 999993^2 = 999986000049 <= Opps, missed this one. 10 down-----. | 999992^2 = 999984000064 | | 999991^2 = 999982000081 | | 999990^2 = 999980000100 | | 999989^2 = 999978000121 | | 999988^2 = 999976000144 | | 999987^2 = 999974000169 <-------------------------------------|---' 999986^2 = 999972000196 | 999985^2 = 999970000225 | 999984^2 = 999968000256 | 999983^2 = 999966000289 <-------------------------------------' 999982^2 = 999964000324  This happens because there is no guarantee that a downward count of the next odd will always end at 9. If ending at 7, 5, 3, or 1, then the next matching first/last digit will be lest than 10 odds away. (9 + 7 + 5 + 3 + 1 + 9 + 7 + 5 + 3 + 1) mod 10 = 0 (7 + 5 + 3 + 1 + 9 + 7 + 5 + 3) mod 10 = 0 (5 + 3 + 1 + 9 + 7 + 5) mod 10 = 0 (3 + 1 + 9 + 7) mod 10 = 0 (1 + 9) mod 10 = 0  To get around this problem without too much work I just did two passes. Pass 1 starts with the highest first/last matching square, pass 2 starts with the 2nd largest. Each pass jumps 10 squares at a time. This reduces the number of iterations by ~1/5. 20,271 iterations to be exact. Lastly I started looking at the 2nd digits. Without much thought you can prove that the 2nd to last digit of all perfect squares is even, unless the last digit is 6. E.g. take squares ending in 9. Only 3*3 or 7*7 end in 9, so...  x + 3 x + 7 x + 3 x + 7 ------------ ----------------- 3x + 9 (7x+4) + 9 x*2 + 3x x*2 + (7x+0) ------------ ----------------- x*2 + 6x + 9 x*2 + (14x+4) + 9  2nd digit will be 6x, and even*anything is even. This is true for 14x+4 as well (note the even carry digit). You can do the rest of this exercise in your head (i.e. avoid doing all the theoretical work yourself with paper and pen), just look at the carry digit, e.g. to end in 9 you must have 3*3 or 7*7, the carry digit is even (i.e. 0 or 4), to end in 6 you must have 4*4 or 6*6, the carry digit is 1 or 3 ending with a even + odd for the 2nd digit. IANS, implementing this will reduce the number of iterations by ~1/2. 8,889 iterations to be exact. 3rd digit? Too much brain power was needed, further optimization will need to be done in the verification. Verification optimization: The first check is the most important check. Taking a hint from Paul Brogger I cut out the center, divided by 11 and checked for FP = 0: 1E-5 × IP 100 MOD 11 ÷ FP X!=0?  Other attempts that set up an efficient way to check the rest of the digits is a waste. The first digit check will happen at each iteration. The probability of a match is only 1:10 making the 2nd check take place ~1/10 of the iterations. Make the first check fast, make the rest source efficient. More optimization can be done, but I made my ~1 hour time target. Finally, I must state how awesome the 42S is. I did all my development using the VI editor and then using txt2raw.pl to convert to raw for import into Free42/Emu42. I was not looking forward to keying this into my 42S for a formal benchmark. After doing so, I must state that there is an attention to detail that I do not think I have seen with any other vertically oriented HP (48GX is close). The orientation of the menus and keys made for very accurate and quick work of entering this code. I applaud the 42S architects. Source with comments: 00 { 279-Byte Prgm } Main loop. DSE from 9 to 1. If 8,7,3,2 skip since perfect squares only end in 9,6,5,4,1,0. If '6' then note the 2nd digits will be odd (start with 9 count down by 2). Evens start with 8 and count down by 2. This is stored in register 08. 01>LBL "PP9" 02 9 03 STO 09 04>LBL 09 05 8 06 STO 08 07 RCL 09 08 X=Y? 09 GTO 10 10 7 11 RCL 09 12 X=Y? 13 GTO 10 14 3 15 RCL 09 16 X=Y? 17 GTO 10 18 2 19 RCL 09 20 X=Y? 21 GTO 10 22 6 23 RCL 09 24 X!=Y? 25 GTO 11 26 1 27 STO+ 08 28>LBL 11 29 XEQ A 30>LBL 10 31 DSE 09 32 GTO 09 33 STOP This is the first called subroutine. It DSE counts from 5 to 1 creating a sequence for LBL B with the first 2 digits to start searching form, (e.g. 98, 96, 94, 92, 90, 69, 67, ..., 10). This will also store the mirror image of the first to digits (REG 13). REG 04 (0 or 1) is used to select the 2 different series of matching first/last squares. 34>LBL A 35 5 36 STO 12 37>LBL 12 38 10 39 RCL× 09 40 RCL+ 08 41 STO 03 42 10 43 ÷ 44 IP 45 RCL 03 46 10 47 MOD 48 10 49 × 50 + 51 STO 13 52 0 53 STO 04 54 XEQ B 55 1 56 STO 04 57 XEQ B 58 2 59 STO- 08 60 DSE 12 61 GTO 12 62 RTN This is where all the work is done. Starting from the largest two digit leading 12 digit number (e.g. 989999999999) find the first or 2nd (check REG 04) square with matching reversed last 2 digits. 63>LBL B 64 RCL 03 65 1 66 + 67 10 68 10^X 69 × 70 1 71 - 72 SQRT 73 IP 74 X^2 75 STO 05 76 LASTX 77 1 78 - 79 X^2 80 - 81 STO 06 82>LBL 00 83 RCL 05 84 100 85 MOD 86 RCL 13 87 X=Y? 88 GTO 01 89 RCL 06 90 STO- 05 91 2 92 STO- 06 93 GTO 00 94>LBL 01 95 RCL 04 96 X=0? 97 GTO 02 98 0 99 STO 04 100 RCL 06 101 STO- 05 102 2 103 STO- 06 104 GTO 00 105>LBL 02 106 10 107 10^X 108 RCL× 03 109 STO 07 110 GTO 04 This is where ~90% of all the computation takes place. The first iteration starts at line 119. Center digits are checked, if no match GTO 03, 10*next odd - 90 to get next square, subtract 20 from next odd to get next odd. If the two leading digits change, exit loop. 111>LBL 03 112 10 113 RCL× 06 114 90 115 - 116 STO- 05 117 20 118 STO- 06 119>LBL 04 120 RCL 07 121 RCL 05 122 XLBL 15 137 -2 138 RCL× 15 139 1 140 - 141 10^X 142 RCL 15 143 5 144 - 145 10^X 146 RCL× 05 147 IP 148 2 149 RCL× 15 150 2 151 + 152 10^X 153 MOD 154 × 155 LASTX 156 10 157 MOD 158 X<>Y 159 IP 160 X!=Y? 161 GTO 03 162 DSE 15 163 GTO 15 164 RCL 05 165 ENTER 166 SQRT 167 STOP 168 .END.  Edited: 5 May 2007, 2:11 p.m.

 Re: HP42S Mini-Challenge: Optimizing !Message #19 Posted by Karl Schneider on 6 May 2007, 1:57 a.m.,in response to message #1 by Valentin Albillo (NOTE: This post was edited to implement the heuristic regarding divisibility by 11, which was identified by others. Only two instructions in my program were changed, reducing execution time by more than 60%.) To get a working and fast program for this challenge, I finally installed Thomas Okken's magnificent Free42 software that I had downloaded quite a while ago. It was quite easy to do; I ought to have done it a long time ago. My intended approach was similar to the one elegantly implemented by "Adam L", which was to convert N2 to a string, then compare the outermost "digit-characters", working toward the middle from each end each time a match was found, and immediately jumping to the next N upon getting a mismatch. Not immediately seeing how to do that with HP-42S string functions, I implemented the same logic with mathematical calculations based on INT and MOD. This is slower and more cumbersome on a physical HP-42S, but it worked. My "ideal" optimized program would incorporate heuristics 3 and 4 into Adam L's tidy code. The heuristics: It is faster and simpler to generate a square and iteratively check for its "palindomicity" than to generate palindromes and check for integer square roots. There are 900,000 possible 12-digit palindromes, which can also be cumbersome to generate. The lowest integer N that produces a 12-digit square is 316,228; the largest is 999,999. The overall search should be restricted to this range of 683,772 possiblities. A squared integer not divisible by 10 can end only with 1, 4, 5, 6, or 9. Since the last digit of N2 must match the first, there is no need to try values of N for which N2 is within the inclusive ranges {200,000 to 399,999} or {700,000 to 899,999}. Therefore, N = 447,214 through 632,457 and N = 836,661 through 948,683 can be bypassed en masse. A palindrome having an even number of digits will be evenly divisible by 11. Therefore, all values of N that are not as such can be skipped over, eliminating 91% of all remaining possibilities. N ending in 0 will yield an N2 ending in 00. If the first two digits were to match, N2 would be only a 10-digit number. Therefore, each N that is a multiple of 10 can be skipped over. In view of the preceding heuristic, however, this may not yield a significant reduction in processing time for the programming effort. For a given value of the leading digit of N2, only one or two ending digits of N will match it. However, checks for this heuristic are a bit cumbersome to implement, and may not save much execution time. So, here's my program, which finds the unique solution working upward from N = 316,228. It runs in only 1.8 seconds on Free42 Binary and 7.2 seconds on Free42 Decimal, on a PC with twin Pentium IV 3.0-GHz CPU's. The program could be easily modified to search from N = 999,999 downward. This would find the answer even faster, as it turns out. Lines 52 and 53 (FIX 00 and RND) were necessary to eliminate floating-point arithmetic errors. Line 57 (ALL display format) is for debugging purposes. 00 { 148-Byte Prgm } 01>LBL "SQ12P" 02 316227 03 STO 00 04>LBL 00 05 1 06 STO+ 00 07 RCL 00 08 11 09 MOD 10 X!=0? 11 GTO 00 12 RCL 00 13 447214 14 X=Y? 15 GTO 06 16 CLX 17 836661 18 X=Y? 19 GTO 07 20 CLX 21 999999 22 X<>Y 23 X>Y? 24 STOP 25 X^2 26 1E11 27 STO 03 28 ÷ 29 STO 02 30 XEQ 01 31>LBL 06 32 632455 33 STO 00 34 GTO 00 35>LBL 07 36 948683 37 STO 00 38 GTO 00 39>LBL 05 40 RCL 00 41 ENTER 42 X^2 43 STOP 44>LBL 01 45 RCL 02 46 ENTER 47 IP 48 STO 04 49 - 50 RCL 03 51 × 52 FIX 00 53 RND 54 ENTER 55 ENTER 56 10 57 ALL 58 MOD 59 STO 05 60 - 61 STO 02 62 RCL 04 63 RCL 05 64 X!=Y? 65 GTO 00 66 RCL 02 67 X=0? 68 GTO 05 69 10 70 STO÷ 03 71 RCL 03 72 STO÷ 02 73 10 74 STO÷ 03 75 GTO 01  Edited: 13 May 2007, 4:20 p.m.

 32 byte, (20 steps in 55 sec.) solution for free42 Mini-Challenge Message #20 Posted by allen on 6 May 2007, 9:04 a.m.,in response to message #1 by Valentin Albillo This was also my first occasion to write a 42s program, though the title of the challenge could be best titled "free42 challenge" since the minimum size contest is likely not practical on a REAL 42S. Accordingly, like Karl, I had to dust off the free42 installation from last year and learn how to use it. What a GREAT program!!! I propose a 32 byte solution using the STAT register as the counter. (mainly because the \sigma+ command automatically puts the increment result on the stack eliminating the need for a 1 STO+ XX RCL XX to bring the value back to the stack.) Runtime is <1min on free42. 00 { 32-Byte Prgm } 01 CL\Sigma ' Clear stat register 02>LBL 00 ‘ Begin counting loop 03 \Sigma+ ‘ Increment STAT register 04 X^2 05 CLA ‘ Clear Alpha register 06 AIP ' Pull result to Alpha reg 07 6 08 STO 01 ' Store counter for length loop 09>LBL 02 ' Begin palindromic check / length loop 10 -1 11 AROT ' Rotate last char to front of ALPHA reg 12 ATOX ' Pull last character code to X 13 ATOX ' Pull first character code to X 14 X!=Y? ' Are the first and last characters equal? 15 GTO 00 ' if not save time by ending loop early and go to couterloop 16 DSE 01 ' if they are, decrement and check for length 17 GTO 02 ' if too short, go to the length loop 18 X=0? ' otherwise was the last result from an empty ALPHA reg? 19 GTO 00 ‘ if yes, return to counter 20 RCL 16 ‘ otherwise SUCCESS!!! – recall the stat N value  Edited: 6 May 2007, 6:33 p.m. after one or more responses were posted

 Re: 41 byte, 7 second solution for free42 Mini-Challenge Message #21 Posted by allen on 6 May 2007, 6:13 p.m.,in response to message #20 by allen Using the heuristic that palindromes are divisible by ll, one can add 4 steps to the program and finish 90% faster: 00 {41-Byte Prgm } 01 CL\Sigma ' Clear stat register 02>LBL 00 ‘ Begin counting loop 03 \Sigma+ ‘ Increment STAT register 04 X^2 05 121 ' ADDED TO CHECK ONLY MULTIPLES OF 11 06 * ' 07 CLA ‘ Clear Alpha register 08 AIP ' Pull result to Alpha reg 09 6 10 STO 01 ' Store counter for length loop 11>LBL 02 ' Begin palindromic check / length loop 12 -1 13 AROT ' Rotate last char to front of ALPHA reg 14 ATOX ' Pull last character code to X 15 ATOX ' Pull first character code to X 16 X!=Y? ' Are the first and last characters equal? 17 GTO 00 ' if not save time by ending loop early and go to couterloop 18 DSE 01 ' if the are, decrement and check for length 19 GTO 02 ' if too short, go to the length loop 20 X=0? ' otherwise was the last result from an empty ALPHA reg? 21 GTO 00 ‘ if yes, return to counter 22 RCL 16 ‘ otherwise SUCCESS!!! recall stat N value 23 11 24 * ' ADDED TO CONVERT couter to X^2 format where X is couter*11  This differs slightly from my initial 44 byte program where I used an (ATOX POSA x=0?) loop similar to Alex's above (ATOX ATOX X=Y?). I was hoping to use the ATOX and POSA commands to create an AND gate so I would not have to process both the length loop and the empty ALPHA loop.

 Re: 41 byte, 7 second solution for free42 Mini-Challenge Message #22 Posted by Alex L on 8 May 2007, 12:34 p.m.,in response to message #21 by allen Add me to the "why didn't I think of that" category with the 11 heuristic. That can be incorporated into my submission at a cost of 4 bytes and 0 steps (plus manually checking 999999), by changing step 01 to 999999, and step 04 to 11. This finishes in under 2 sec on Free42, which leads me to believe it should be just over an hour on a physical 42S, which puts it into the range of respectability. Perhaps I'll check. :) Of course it's no longer necessarily going to work for the general case. -- complete updated program -- 01 999999 02 STO 01 03 LBL 01 04 11 05 STO- 01 06 RCL 01 07 X^2 08 CLA 09 AIP 10 LBL 02 11 ALENG 12 2 13 X>Y? 14 GTO 03 15 -1 16 AROT 17 ATOX 18 ATOX 19 X=Y? 20 GTO 02 21 GTO 01 22 LBL 03 23 RCL 01 24 ENTER 25 X^2 

 Re: 41 byte, 7 second solution for free42 Mini-Challenge Message #23 Posted by Gerson W. Barbosa on 8 May 2007, 9:31 p.m.,in response to message #22 by Alex L Hello Alex, Congratulations for your tiny versions. The MOD(11) heuristics others have found is a killer one indeed. I added it to the simple 71B program I had written yesterday (too lazy to write a 42S or 33S version; besides, just a variation of what has already been written). I've just run your latest version on my HP-42S: 1 hour 3 minutes. Here is the HP-71 program: 10 DESTROY ALL @ T=TIME 20 FOR N=999999 TO 316228 STEP -11 30 X$=STR$(N*N) @ I=0 @ S=0 40 I=I+1 50 IF X$[I,I]#X$[13-I,13-I] THEN 80 60 S=S+1 @ IF I<6 THEN 40 70 IF S=6 THEN DISP X$;TIME-T @ END 80 NEXT N >run 637832238736 15.02  15 seconds @ 500 MHz, about 26 minutes on the real 71B. 144 bytes. By the way, the latest version of J-F Garnier's Emu71 (2006) is a pleasure to use: copy and paste to and from the DOS window works nicely. I have to remember to upgrade to the registered version, even though I still don't have the serial interface :-) Regards, Gerson.  Re: HP42S Mini-Challenge: Optimizing !Message #24 Posted by Werner on 7 May 2007, 7:49 a.m.,in response to message #1 by Valentin Albillo Second try.. heuristics: - palindromes with an even nr of digits are divisible by 11, so x has to be divisible by 11 as well. - if x ends with digit i, y starts/ends with digit i^2 MOD 10 and x is between SQRT(i*10^11) and SQRT((i+1)*10^11) We'll loop over the 'ending digits' and determine the range to check. Within that range, only multiples of 11 ending in the same digit have to be checked. timing: Emu42 @ 3Ghz: 9s It should be noted that since the result is obtained with ending digit 4, counting upwards would've been faster still. { 115-Byte Prgm } *LBL "PSX" 9 STO 01 *LBL 01 loop over i=9..1 step -1 RCL 01 X^2 10 MOD 1e11 STO* ST Y X<>Y STO+ ST Y XEQ 90 determine x boundaries STO 02 RDN XEQ 90 STO 03 *LBL 02 inner loop X^2 1e6 / ENTER *LBL 03 palindrome test RDN X=0? RTN R03 contains x 10 xy,yx / x,yyx IP LASTX FP 0,yyx x 100 * + LASTX IP STO- ST Y yy x,x 11 MOD X=0? GTO 03 RCL 02 RCL 03 110 steps of 110 ensure that x remains divisble by 11 and - retains the same ending digit STO 03 X#Y? GTO 02 DSE 01 GTO 01 RTN *LBL 90 determine x so that [11*(i + 10*x)]^2 < X SQRT 11 / RCL 01 - 10 / IP 10 * RCL 01 + 11 * END   Re: HP42S Mini-Challenge: Optimizing !Message #25 Posted by Werner on 7 May 2007, 3:36 p.m.,in response to message #24 by Werner a few corrections: the intro should read: - palindromes with an even nr of digits are divisible by 11, so x has to be divisible by 11 as well. - if x ends with digit i, y starts/ends with digit j = i^2 MOD 10 and x is between SQRT(j*10^11) and SQRT((j+1)*10^11) Since x also has to be a multiple of 11, we have: SQRT(j*10^11) < x < SQRT((j+1)*10^11) < 11*(10*z + i) < We'll loop over the 'ending digits' i=9..1 and determine the range to check. Within that range, only multiples of 11 ending in the same digit have to be checked. And the length of the program is 112 Bytes, not 115   Re: HP42S Mini-Challenge: Optimizing !Message #26 Posted by Werner on 8 May 2007, 2:17 a.m.,in response to message #25 by Werner Third, and final, try. p = x^2 Basically the same program as in #2, but counting the last two digits of x, and determining the corresponding range of p. Runs in a true HP42S in under 3 minutes, uses R01-R03 { 137-Byte Prgm } *LBL "PS3" 99 STO 01 *LBL 01 loop over ij=99..1 step -1 RCL 01 X^2 100 MOD yx = ending digits of palindrome 10 / IP LASTX FP X=0? GTO 00 100 * + xy = starting digits 1e10 STO* ST Y X<>Y STO+ ST Y XEQ 90 determine x boundaries STO 02 RDN XEQ 90 STO 03 *LBL 02 inner loop X^2 1e6 / ENTER *LBL 03 palindrome test RDN X=0? RTN R03 contains x 10 xy,yx / x,yyx IP LASTX FP 0,yyx x 100 * + LASTX IP STO- ST Y yy x,x 11 MOD X=0? GTO 03 RCL 02 RCL 03 1100 steps of 1100 ensure that x remains divisible by 11 and - retains the same ending digits STO 03 X#Y? GTO 02 *LBL 00 DSE 01 GTO 01 RTN *LBL 90 determine x so that [11*(ij - j*10 + 100*x)]^2 < X SQRT endures x ends in ij and is divisible by 11 1100 / IP 100 * RCL 01 10 MOD LASTX * RCL 01 - - 11 * END   Re: HP42S Mini-Challenge: Optimizing !Message #27 Posted by Egan Ford on 7 May 2007, 3:50 p.m.,in response to message #24 by Werner Quote: - palindromes with an even nr of digits are divisible by 11... Ugggg! How did I miss this? It was trival to prove too. I applied the following patch to my last submission and get 9s with Emu42 @ 1.7 GHz Pentium M. Thanks. 1c1 < LBL "PP9" --- > LBL "PP11" 87a88,94 > GTO 21 > GTO 22 > LBL 21 > RCL 05 > 11 > MOD > X=0? 88a96 > LBL 22 112c120 < 10 --- > 110 114c122 < 90 --- > 11990 117c125 < 20 --- > 220   Re: HP42S Mini-Challenge: Optimizing !Message #28 Posted by Howard Owen on 7 May 2007, 6:16 p.m.,in response to message #27 by Egan Ford Great, Egan! But where am I going to get a patch(1) binary for my 42S? 8) Regards, Howard  Re: HP42S Mini-Challenge: Optimizing !Message #29 Posted by Egan Ford on 7 May 2007, 6:39 p.m.,in response to message #28 by Howard Owen Quote: But where am I going to get a patch(1) binary for my 42S? Sorry, source http://sense.net/~egan/pp11.txt and binary http://sense.net/~egan/pp11.txt.raw .  Re: HP42S Mini-Challenge: My Original Solution & CommentsMessage #30 Posted by Valentin Albillo on 9 May 2007, 7:21 p.m.,in response to message #1 by Valentin Albillo Hi all, First of all, thank you very much for the overwhelming response to this 42S mini-challenge. Awesome solutions have been produced and though I should pretty much be used to it by now, I'm continually amazed at the ingenuity displayed by so many contributors, both frequent posters and newcomers alike. I'm sure we all have learned a lot from these excellent solutions and added a lot of fine techniques and brilliant ideas to our arsenal of programming knowledge, not only HP42S-related but general in nature. For the record, I'll give and briefly discuss my original solutions. I initially wrote the (b) case solution, then suitably modified it to also cover cases (a) and (c). My rationale was as follows: the task consisted of finding a 12-digit palindromic square as easily and fast as possible. Two approaches came to mind immediately: Generate all squares in the required range (3162282 to 9999992, in steps of 11 (because a palindromic even-digit number is necessarily a multiple of 11, thus its square root must be as well as 11 is a prime number), and test them for palindromicity. This amounted to some 62000 candidates, thus some 31000 on average. Generate all 12-digit palindromes from 100000000001 to 980000000089 subject to some simple heuristics, and test them for squaredness. Both approaches seemed feasible but I decided that it would probably be a lot easier and faster to test for squaredness (which can be done in just 3 fast steps) than testing for palindromicity, which is more involved and slow, so the second option seemed easier as long as I could devise a fast, simple procedure for directly generating 12-digit palindromic numbers and further, to only generate those which had a chance of being perfect squares, thus reducing the number of candidates to a reasonable minimum. This I could do, so I opted for the second approach. My program for the case (b) below directly generates 12-digit palindromes in a very fast way, using pre-stored constants which are quickly initialized once at the beginning of the program, and taking all loop invariants out of the innermost loops, so that redundant arithmetic operations are avoided. The following extremely simple heuristics are used: We only need to loop from 100000 to 999999, the first six digits of the palindrome, as the remaining 6 are simply the mirror image of these, thus a maximum of some 900000 loops would be needed Further, a perfect square can only end in the following digits: 01,04,09,16,21,24,25,29,36,41,44,49,56,61,64,69,76,81,84,89,96 the termination 00 being discarded as otherwise the palindromic number would begin by 00 and thus be just a 10-digit number. These ending sequences must of course also appear (reversed) at the beginning of any candidate, thus limiting the maximum number of cases to try to some 210000 in the worst case, an average of about only 105000 statistically probable. This is about 3 times as many candidates as the first option, but requiring a much simpler and faster test per candidate so it seemed plausible to go this way. Assuming I could generate the palindromic candidates very fast subject to these constraints, and as the squaredness test was just 3 fast steps, I considered that 105,000 cases (average) to try was perfectly feasible even on a physical HP42S. This is the resulting 72-step (157-byte) program:  01 LBL "P" 19 x 37 LBL 02 55 GTO 04 02 (see *1) 20 LASTX 38 RCL 04 56 Rdown 03 (see *1) 21 RCLx 04 39 STO 02 57 RCL+ 08 04 1000000100 22 LASTX 40 RCL 10 58 DSE 02 05 STO 06 23 RCL/ 04 41 LBL 03 59 GTO 03 06 100001E3 24 IP 42 RCL 04 60 RCL 07 07 STO 07 25 RCLx 05 43 STO 03 61 STO+ 10 08 1001E4 26 - 44 Rdown 62 DSE 01 09 STO 08 27 + 45 ENTER 63 GTO 02 10 11E5 28 VIEW ST X 46 LBL 04 64 RCL 06 11 STO 09 29 STO 11 47 ENTER 65 STO+ 11 12 10 30 RCL 04 48 SQRT 66 DSE 00 13 STO 04 31 STO 00 49 FP 67 GTO 01 14 99 32 LBL 01 50 X=0? 68 GTO 00 15 STO 05 33 RCL 04 51 GTO 05 69 LBL 05 16 LBL 00 34 STO 01 52 Rdown 70 LASTX 17 1E10 35 RCL 11 53 RCL+ 09 71 X^2 18 ATOX 36 STO 10 54 DSE 03 72 END *1: - line 2 is alpha text formed by the following ASCII characters: 10,40,90,61,12,42,52,92,63,14,44,94,65,16,46 - line 3 is appended alpha text formed by the following ASCII characters: 96,67,18,48,98,69 All of them are keyable from the ALPHA entry menus. This is an image of how they should look like as program lines:  As you can see, an added finesse is to have all 21 possible beginning (i.e., reversed ending) sequences stored as ALPHA characters in the ALPHA register, from which they are easily taken out, one at a time, with a simple ATOX instruction. This is fast and saves many program steps/bytes and/or registers. The resulting program find the only solution,  637,832,238,736 = 798,6442  in just 2 h 42 min in a physical HP42S, 85 seconds in Emu42 @ 2.4 Ghz, and 44 seconds in Free42 @ a very modest Palm Z100. Once I had this solution, I created the one for case (c) by simply unrolling the innermost loop, like this:  ... 41 LBL 03 42 ENTER 43 ENTER 50 ENTER 113 Rdown (line 56 of (b)) 44 SQRT 51 SQRT 114 RCL+ 08 (line 57 of (b)) 45 FP 52 FP ... ... (etc) 46 X=0? 53 X=0? ... 129 END 47 GTO 05 54 GTO 05 ... 48 Rdown 55 Rdown 49 RCL+ 09 56 RCL+ 09  which produces a 129-step (239-byte) program which, as compensation for these extra steps, runs much faster, finding the solution in 1 h 48 min in a physical HP42S, 56 seconds in Emu42 @ 2.4 Ghz, and 29 seconds in Free42 @ Palm Z100. Thus it's quite clear that when speed does matter a lot, and in certain architectures, unrolling the innermost loop or loops actually pays handsomely. As for the case (a) solution, it was just the one for case (b) with all the heuristics and finesses removed, which made it much shorter but unbearably slow. We've seen much better case (a) solutions posted here so it doesn't bear posting it. By the way, I'm including here my case (a) solution for the HP-71B as a bonus, which is the following 2-line (58-byte) program (STD display mode is assumed):  1 FOR I=999999 TO 316228 STEP -11 @ S$=STR$(I*I) @ IF S$=REV$(S$) THEN DISP I,S$@ END 2 NEXT I  It does find the unique solution in just 3 seconds under Emu71 @ 2.4 Ghz, about 12 min. in a physical HP-71B. Apart form reversing the loop, I don't think it can be made much simpler :-) Again, thanks a lots for your valuable and superb inputs and get ready for the next one, it will be tougher and that's a promise. Best regards from V. Edited: 9 May 2007, 7:32 p.m.  Re: HP42S Mini-Challenge: My Original Solution & CommentsMessage #31 Posted by Gerson W. Barbosa on 9 May 2007, 7:56 p.m.,in response to message #30 by Valentin Albillo Hi Valentin, Quote: By the way, I'm including here my case (a) solution for the HP-71B as a bonus, which is the following 2-line (58-byte) program:  1 FOR I=999999 TO 316228 STEP -11 @ S$=STR$(I*I) @ IF S$=REV$(S$) THEN DISP I,S$@ END 2 NEXT I I have printed out both the HP-71 and the Math Pac Owner's Manual. I should have printed out the one with REV$ keyword :-) Thanks for another MO&C, especially the extra bonus :-) Best regards, Gerson.

 Re: HP42S Mini-Challenge: My Original Solution & CommentsMessage #32 Posted by Valentin Albillo on 10 May 2007, 9:00 a.m.,in response to message #31 by Gerson W. Barbosa Hi, Gerson: Gerson posted: "I have printed out both the HP-71 and the Math Pac Owner's Manual. I should have printed out the one with REV$keyword :-)" Thanks for your kind words of appreciation and for your posted contributions to this mini-challenge. I'm sure you are already aware but just in case, the REV$ keyword is not available in a bare-bones HP-71B. It resides in a number of LEX (Language EXtension) files, such as STRUTIL, for instance, which can be copied to RAM or used from some ROM or EPROM. It's also simple enough that it can be very easily POKEd in as well with a fairly small program or even manually. For people using Emu71, the basic freeware install does include the STRUTIL LEX file already resident at :PORT(5), as you can check by using CAT, so REV$is already immediately available. As I use Emu71 to develop my programs and create my challenges, mini-challenges, and articles, I usually include in them the functionality afforder by Emu71 right from installation, which means: - all Math ROM keywords (e.g.: MAT A=INV(B)) - all HP-IL keywords (e.g.: BIT, etc) - all STRUTIL keywords (e.g.: REV$, RPT$, etc) Also, the physical HP-71B is typically available with an HP-IL ROM already plugged in, though getting a physical Math ROM is certainly much more difficult, but its incredible usefulness more that justifies any effort to get one and, IMHO, you don't have a full HP-71B unless you have one plugged in. Best regards from V.  71B...Message #33 Posted by Gene on 10 May 2007, 3:20 p.m.,in response to message #32 by Valentin Albillo I'm fortunate enough to have a physical 71B with the math rom and extra ram installed *internally*. Leaves front ports open for the 41 translator, JPC X, etc. :-)  Re: 71B...Message #34 Posted by Valentin Albillo on 10 May 2007, 5:41 p.m.,in response to message #33 by Gene Yes, very interesting, good for you ... What about the determinants ? :-) :-) Best regards from V.  Re: HP42S Mini-Challenge: My Original Solution & CommentsMessage #35 Posted by Gerson W. Barbosa on 10 May 2007, 9:17 p.m.,in response to message #32 by Valentin Albillo Hi Valentin, Quote: I'm sure you are already aware but just in case, the REV$ keyword is not available in a bare-bones HP-71B. Yes, I knew REV$was not a standard keyword when I noticed it wouldn't run on my physical HP-71B. I thought it was because mine is 1BBBB version, so your explanation has been much appreciated. I was not lucky enough to have owned one when it was released. It was simply out of my reach! But I am lucky enough to have one now with the Math ROM as per your advice. I have also a card reader, though I believe an RS-232 interface would be more useful. I'm about to add a 32KB RAM module, which shoud be enough. Since I am not familiar with the HP-71B yet, my programs tend to be longer than they ought to be. For instance, to get the following output formatted the way I wanted R(4) 50º 07' 06" NW I had to use almost two full lines: 280 M$=CHR$(48*(2-LEN(STR$(M))))&STR$(M) @ S$=CHR$(48*(2-LEN(STR$(S))))&STR$(S) 285 DISP "R(";STR$(I);")";TAB(T);D$;CHR$(167);" ";M$;"' ";S$;CHR$(34);" ";X$ Perhaps this could have been done with format strings, but I haven't figured a way to use them in this case. Reading the manuals might help :-) Best regards, Gerson.

 Re: HP42S Mini-Challenge: My Original Solution & CommentsMessage #36 Posted by Valentin Albillo on 11 May 2007, 7:27 a.m.,in response to message #35 by Gerson W. Barbosa Hi, Gerson: Gerson posted: "Perhaps this could have been done with format strings, but I haven't figured a way to use them in this case." Try this:  1 I=4 @ M=7 @ S=6 @ T=10 @ X$="NW" @ D$="50" 2 ! 280 M$=CHR$(48*(2-LEN(STR$(M))))&STR$(M) @ S$=CHR$(48*(2-LEN(STR$(S))))&STR$(S) 285 DISP "R(";STR$(I);")";TAB(T);D$;CHR$(167);" ";M$;"' ";S$;CHR$(34);" ";X$290 ! 300 DISP USING "'R(',D,')',5X,2A,B,2(X,2Z,B),X,2A";I,D$,167,M,39,S,34,X\$ >RUN R(4) 50º 07' 06" NW R(4) 50º 07' 06" NW  where lines 1 and 2 simply set up some variables to mimic the ones you're using in your code, lines 280 and 285 are your own posted coded, and line 300 is my suggested version, which seems to do what you want in a simpler way. As you can see in the sample RUN, both your code and my line 300 code do produce exactly the same output for this particular example of yours. You may want to fine-tune it as you need to cover other more general cases in your program. If the exact same format is to be used more than once at several different places, put it in their own IMAGE statement (say line 900 IMAGE ..., and then simply DISP USING 900; .... This will be simpler and more easy to maintain, as you would need to change just the image at line 900 to have the changes propagate to all DISP statements using it, instead of having to change them one by one, individually. Best regards from V.

 Re: HP42S Mini-Challenge: My Original Solution & CommentsMessage #37 Posted by Gerson W. Barbosa on 11 May 2007, 10:28 a.m.,in response to message #36 by Valentin Albillo Hi Valentin, Considering the HP-71B is relatively new to me, I was pleased with my HP-71B port of a CASIO PB-700 program I wrote years ago, except for those two lines. I will follow your suggestion in the definitive version. The Owner's Manual doesn't cover formatting strings properly. A glance at the Reference Manual seemed more promising to me. I will print it out as well. Thank you very much for the free lesson! :-) Best regards, Gerson.

Go back to the main exhibit hall