Search

 Search WWW Search DelphiForFun.org

As of October, 2016, Embarcadero is offering a free release of Delphi (Delphi 10.1 Berlin Starter Edition ).     There are a few restrictions, but it is a welcome step toward making more programmers aware of the joys of Delphi.  They do say "Offer may be withdrawn at any time", so don't delay if you want to check it out.  Please use the feedback link to let me know if the link stops working.

Support DFF - Shop

If you shop at Amazon anyway,  consider using this link.

We receive a few cents from each purchase.  Thanks

Support DFF - Donate

If you benefit from the website,  in terms of knowledge, entertainment value, or something otherwise useful, consider making a donation via PayPal  to help defray the costs.  (No PayPal account necessary to donate via credit card.)  Transaction is secure.

Mensa® Daily Puzzlers

For over 15 years Mensa Page-A-Day calendars have provided several puzzles a year for my programming pleasure.  Coding "solvers" is most fun, but many programs also allow user solving, convenient for "fill in the blanks" type.  Below are Amazon  links to the two most recent years.

(Hint: If you can wait, current year calendars are usually on sale in January.)

Contact

 Search DelphiForFun.org only

Problem Description

For a given power value, find all numbers greater than 1 which are equal to the sum of their digits raised to that power.  For example:  370=33+73+03.

Background & Techniques

This problem is from an article "Are Toy Problems Useful" written by Donald Knuth, published in the February , 1977 issue of Popular Computing magazine,  I found it reprinted in "Selected Papers on Computer Science:, Donald E. Knuth, Cambridge University Press, 1996.  The articled challenged claims by G. H. Hardy that trivial problems were useless and a waste of time.  Knuth believes, and I agree, that such problems are useful if a encourage and reinforce problem solving skills in the same sense that story problems in your Algebra or Calculus textbook are useful.

This one in particular proved challenging because my standard "Brute Force" approach  works OK for single digit powers but finding the single number equal to the sum of the 10 powers of its digits takes 25 minutes on my medium speed laptop.

The program allows users to enter a Power value between 2 and 15 and has buttons for each of 3 methods implemented.

Button 1 tests all permutations with repeats for N digit integers. We'll call this "Brute Force 1"and it works
well up to about N=8 (sum of 8th powers of digits equal to the number being tested).  Button 1 checks only number with N digits.

Button 2 tried a second way to generate all permutations with repeats, simply counting, looking at all numbers
from the starting point up to some limit. All of Knuth's examples showed N digit solutions for a
given exponent, N. I spent several hours without success trying to prove that this was always true. Button
2 revealed that in fact there is at least one case where it is not so when checking digits with N-1, N, or N+1 digits.

Button 3 is the best solution so far. It solves the N=10 case less than 2 seconds compared to 30 minutes
for Button 1 and about 2 hours for Button 2. I will leave the description to be revealed in a separate form in
case you would like to work on the puzzle yourself. Like Button 2, Button 3 checks combinations with N-1 to N+1 digits.

Programmer's Notes:

The program uses several components from our DFFLIB library and any recent version will be required before recompiling the program.   UComboV2 is used to generate permutations and combinations.  UIntList, used in Button 3, lets us create an  integer list of number "signatures" and the array of digits represented.

Because it is easy here to start processes which may run for hours, provisions are made for the user to interrupt execution.  The technique used in many programs here on DFF is as follows:

 Establish a "Stop" button which will set a Tag property field of the form or some other control to a non-zero value. In the code section with the long running loop, initialize the Tag value to 0 and a Loop counter field to 0 before entering the loop. Within the loop, check for Tag value <> 0 and break out of the loop if found.' Also within the loop, set up a test which increments the loop counter and when the counter value meets a test condition, execute Application.ProcessMessages to allow any user requests, including a click on the Stop button to be handled.  I typically use code like this inc(loopcount); If loopcount and \$FFFF then Begin    {Update progress bar or label if desired}    Application.ProcessMessages; End; This will trigger a check every 65,536 times through the loop.  Adjust this value to allow the check every second or so.  Application.ProcesssMessage is quite expensive time-wise so the tradeoff is between program efficiency and forcing the user to wait a bit before exiting.

The Stop button in this case is made large enough to to cover all three buttons and is initially moved to the top left corner of the top button.  It is initially and normally has its Visibility property set to False. Entering the Button click exit, sets the Stop button Visible to True and sets it back to False before exiting the procedure.