[VA] Short & Sweet Math Challenges #23: "May the 4th Be With You !" Special
|
10-24-2019, 01:26 PM
(This post was last modified: 11-05-2019 12:47 PM by Jeff O..)
Post: #47
|
|||
|
|||
RE: [VA] Short & Sweet Math Challenges #23: "May the 4th Be With You !" ...
I'm guessing no one was expecting an update regarding further work on this, but a couple of recent things brought it back to my attention. First, the HHC 2019 programming contest was related, and second, Valentin's posting of his web site led me to re-read his challenge and my input. For posterity’s sake, I decided to go ahead and add my new work to the original thread. (Apologies in advance for the length of this post, brevity is not a strength of mine.)
As noted in my old post above, I ended up solving the sixth part of Valentin's challenge, with optimizations to reduce the search space, but with the knowledge that other portions of the program were decidedly not optimized. I was particularly dissatisfied with my method to determine if the digits in the sum of the digits to the n-th power were a permutation of the digits in the n-digit input number: (06-22-2018 08:20 PM)Jeff O. Wrote: I did this in what I am sure is a very clunky fashion: As I said, I found the above dissatisfying, but the program worked, Valentin wrapped up the challenge, and I returned to the mundane tasks of everyday life. After the HHC 2019 programming contest was presented, I realized that it was related to Valentin's challenge, limited to 3-digit numbers and eliminating the "selfie" constraint, i.e., just looking for 3-digit numbers whose digits to the 3rd power summed to the input number, not the reverse. After creating a brute-force method to solve the programming contest, I revisited my "selfie" program to see how it might be used. First I removed the few lines that did the "selfie" part, and it quickly found the four answers to the contest. Then somewhere along the line I re-read my old post, remembered my dissatisfaction and decided to see if I could improve on the previous version, especially the permutation identification part quoted above. When I originally worked on the problem, I tried to think of a better way to do it. Doing it manually, I envisioned something like the following process: 1. Write down both numbers 2. Pick a digit in the first number, look for it in the second 3. If a is match found, mark out the digit from each number, go back to step 2. If all digits get checked and matched, go to step 5. If they do not match, go to step 4. 4. If a match for any digit in the input number cannot be found in the second, the numbers cannot be permutations of each other. 5. All digits found and uniquely matched, so the numbers are permutations of each other. For example, check 12345 against 34521 Pick the 5 from 12345, matches the 5 from 34521, strike out both, leaving 1234X vs. 34X21. These might be re-written as 1234 and 3421. Now check the 4, leaving 123X vs. 3X21 or 123 vs. 321, and so on until checking 1 vs. 1, and thus finding the two starting numbers to be permutations of each other. Now check 12745 vs. 34521. As above, 5 matches 5, leaving 1274X vs. 34X21 (or 1274 vs. 3421), 4 matches 4, leaving 127XX vs. 3XX21 (127 vs. 321). The next time around, 7 is not found in 321, so we abort the check and declare that the originals are not permutations. (I’m sure the above described procedure is quite simple and obvious to MoHPC Forum members, but I find it useful to spell out even the simple things, so I may remember them more readily in the future should the need arise.) For the purposes of the following discussion, the “first” number is the sum of the digits of the input number to the n-th power, and the “second” number is the input number. I think I considered the above method back in 2018 but got hung up on how I might check each digit and delete matches. It sounded like a lot of breaking, shifting and re-storing that did not immediately seem to be much if any better than my dissemble-sort-reassemble method. That’s when I dropped further work. When I returned to the problem recently, I revisited the above described manual procedure, and realized that rather than delete the digits as checked and repack to create new numbers, if I could find a way to identify that a match had been found and no longer check those digits, I would not need to reassemble at each step. It is relatively easy to extract single digits from the first number and create a number with one less digit, so each digit is eliminated from further checking at each step. For checking against the second, I determined that I did not need to eliminate the matches and reconstitute the second number without that digit, I just needed to make sure that a digit could not be matched again. So if a match is found, rather than delete and re-assemble, I changed that digit to a value that could not be a match to any further digits extracted from the original number. My input numbers were generated by the method I used (described below) as individual digits in sequential storage registers. So if a match was found, I stored pi in the register that held the matching digit. I was then free to check all future digits against all registers that represented the second number with no possibility that that digit could be matched again. With a bit of work, I was able to implement the above method, and pleased to find that it worked quite well. The revised program is reduced to 120 steps compared to 143 of the original, plus the need for the separate 23 step SORT routine is eliminated. With the above major change and a couple of other improvements, the new version runs in less than half the time of the original. On my DM42, all selfies are found in 1 hour and 9 minutes vs. 2 hours 34 minutes of the original. With Free42 on my desktop, it finds them all in 18 seconds vs. 45 seconds for the original program. I'm fairly happy with the improvement, but I may continue looking for refinements, as it is an enjoyable pastime. (edit - see below for an update to this post and the following post for a new method.) Here is the code: Code: 000 { 209-Byte Prgm } My number generator generates the following sequence of numbers to check (read top to bottom, left to right): Code: 1 13 26 44 79 118 226 399 ... 3333 ... 111111111 ... In case it is not immediately apparent what is going on with the above sequence of numbers to check, a description of the procedure used to create the sequence is as follows: 1. Start with all 11 registers representing the (up to) 11 digit number set to zero. 2. Recall the digit in the ones position 3. Is it 9? 4. If not, increment it, the 11 registers now represent the next number. Check for sum d^n being a permutation, then return to step 2. 5. If it is equal to 9, check the digit to the left in the tens position. 6. Is it 9? 7. If not, increment it and also set the value in the ones position to that new value, the 11 registers now represent the number to be evaluated. 8. If it is equal to 9, check the digit to the left in the hundreds position. 9. Is it 9? 10. If not, increment it and also set the values in the tens and ones positions to that new value, the 11 registers now represent the next number to be evaluated. 11. If it is equal to 9, check the digit to the left in the thousands position. 12. And so on. To be honest, I'm not quite sure how I arrived at the above method to create the sequence of numbers. It took me a while to figure out how it worked and what I was doing in my program again after 15 months. Probably some well-known technique that I stumbled upon. The full listing of all numbers generated by the above procedure would include 167,959 numbers. The interested reader will likely notice that the above listing contains no numbers that include any zeros. Yet there are several numbers containing at least one zero which satisfy the goal that the digits of the n-digit number raised to the n-th power sum to the n-digit number itself. I developed and checked those as follows. After generating and checking each of the above numbers, I then padded them with zeros. So for a single digit number, say 5, I checked 5, 50, 500, 5000,…, 50 000 000 000. I did not raise the zeros to the higher powers, I only raised the original non-zero digits to the higher powers and summed those. This requires checking 11 numbers for every single-digit number in the above list, 10 numbers for every 2-digit number, 9 numbers for each 3-digit, etc. on up to 1 number for each 11-digit number in the above list. That increases the total count of the numbers needing to be checked to 352,704. Still quite a small fraction (0.0003527%) of the 99,999,999,999 numbers which would have to be checked via a brute-force method. Last but not least, attached is a zipped raw file in case you would like to play with the program in Free42 or your DM42. If you would like to simply determine those n-digit numbers whose digits raised to the n-th power sum to themself, i.e., remove the selfie constraint (and who wouldn't?), delete steps 93 through 109. Edit - as expected, I continued to attempt to improve my program. In an effort to speed it up, I developed a new way to determine the number of digits in the current number developed by my above described method. It appears to be only about 1% faster, so not as much improvement as I had hoped. But it is 6 steps shorter, so I would call it a better effort. I replaced the program listing above with the new version, and have attached a new zipped raw file. The original raw file is still attached for posterity. Dave - My mind is going - I can feel it. |
|||
« Next Oldest | Next Newest »
|
User(s) browsing this thread: 3 Guest(s)