| As usual, we commence with working
out a suitable search
range. We want to work with
4-digit integers, so they'll be between 1000 and 9999. But these must all be composed of distinct digits, so the range must be further restricted to suit: 1234 to 9876. However the larger numbers must be multiples of smaller integers. The minimum factor is 2, so the maximum value for a small integer is 9876/2 = 4938. So the search range will have be 1234 to 4938. What factors should we use? We already know the smallest is 2. The largest is that which will not permit the smallest integer to exceed 9999 when multiplied by it. 8 x 1234 = 9872, which is ok, but 9 x 1234 = 11106, which is too large, so the factor range is 2 to 8. With these matters settled, let's write some code! |
| '
Puzzzlet #092 ' To find a 4-digit integer, composed ' of four different digits (A), and an ' anagram of it (B), such that A is a ' factor of B. ' Example 1782 x 4 = 7128 ' By Dave Ellis. declare AllDigitsDifferent(a: int) declare IsAnagram(str1$: string, str2$: string) declare PrintIt(p1: int, p2: int, p3: int) def flag, it1, it2, it3: int def string1$, string2$: string openconsole print "Searching ...": print for it1 = 1234 to 4938: 'integer if AllDigitsDifferent(it1) it2 = 2: 'factor flag = -1 do it3 = it1 * it2: 'integer*factor if it3 > 9999 flag = 0: 'too big - exit do else if IsAnagram (str$(it1), str$(it3)) PrintIt (it1, it2, it3) endif endif it2 = it2 + 1 until flag = 0 | it2 > 8 endif next it1 print: print "No More!" print: print "Press a key to exit ... ", do: until inkey$ <> "" closeconsole end sub AllDigitsDifferent(a) ' if all the digits in argument a are ' different, returns -1, else returns 0 def flag, i, j, L: int def a$, p$, q$: string a$ = ltrim$(str$(a)) L = len(a$) i = 1 flag = -1 do j = i + 1 do p$ = mid$(a$, i, 1) q$ = mid$(a$, j ,1) if q$ = p$ flag = 0 endif j = j + 1 until flag = 0 | j > L i = i + 1 until flag = 0 | i > L - 1 return flag sub IsAnagram(str1$, str2$) ' if str1$ is an anagram of str2$, ' returns -1, else returns 0. def i$, j$, test$: string def flag, i, j, L1, L2: int test$ = str2$ L1 = len(str1$) L2 = len(test$) if L1 <> L2 flag = 0 else for i = 1 to L1 i$ = mid$(str1$, i, 1) j = 1 flag = -1 do j$ = mid$(test$, j, 1) if i$ = j$ replace$(test$, j, 1, "X") flag = 0 endif j = j + 1 until flag = 0 | j > L2 next i flag = (test$ = string$(L1, "X")) endif return flag sub PrintIt(p1, p2, p3) ' pretty printer print p1, "x ", print p2, "= ", print p3 return |
| PROGRAM NOTES The usual top-down approach is applied to this program. The main routine tells you everything you need to know. In the following extract, the lines are numbered to make it easier to follow the description. |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
for it1 = 1234 to 4938: 'integer if AllDigitsDifferent(it1) it2 = 2: 'factor flag = -1 do it3 = it1 * it2: 'integer*factor if it3 > 9999 flag = 0: 'too big - exit do else if IsAnagram (str$(it1), str$(it3)) PrintIt (it1, it2, it3) endif endif it2 = it2 + 1 until flag = 0 | it2 > 8 endif next it1 |
| Now to provide an exegesis of the code, using the line numbers above: |
| 1 |
for it1 = 1234 to 4938. Opens the main FOR-NEXT loop, using variable it1 as iterator. Note that the range used, 1234 to 4938, is as discussed in the introductory notes. |
| 2 |
if AllDigitsDifferent(it1). The specification says all the digits of the answer must be different, so it1 is passed to function AllDigitsDifferent() to test for this. The function returns -1 (TRUE) or 0 (FALSE) as appropriate. |
| 3 |
it2 = 2. Variable it2 is used to hold the multiplying factor. Its minimum value will be 2, as discussed in the introductory notes, and it's initialised to that here. |
| 4 |
flag = -1. Variable flag is used as indicator of failure (meaning that the integer currently being investigated is not a solution). It's initialised here to -1 (TRUE). This means we're assuming we have a solution until test prove otherwise. |
| 5 |
do. Opens the DO-LOOP. Remember, this is nested within the main FOR-NEXT loop. The arrangement is that the outer loop controls the integers and the inner loop controls the factors. So each integer is tested with all appropriate factors. |
| 6 |
it3 = it1 * it2. The integer it1 is multiplied
by factor it2 and the result
stored in variable it3. |
| 7 |
if it3 > 9999. The specification implies that this product must not be greater than 9999, and this line tests that the requirement is met. |
| 8 |
flag = 0. If it3 is too big, flag is set to 0 as an indication that this particular integer isn't going to be a solution. |
| 9 |
else. If the test at line 7 was passed successfully, we can go on to a final test on the next line. |
| 10 |
if IsAnagram (str$(it1), str$(it3)). The original integer and the product of that integer and a factor should be anagrams of each other. This line tests for "anagramicity" by passing them to the function IsAnagram(). If IsAnagram()'s arguments are anagrams of each other, it returns -1 (TRUE), otherwise 0 (FALSE). Note that the parameters are converted to strings before being passed, since IsAnagram() is expecting string inputs. |
| 11 |
PrintIt (it1, it2, it3). If the test at line 10 is passed, we have a solution and the subroutine PrintIt() is called to print the data to the screen. |
| 12 |
endif. Housekeeping - closes the inner IF-ENDIF loop. |
| 13 |
endif. Housekeeping - closes the outerer IF-ENDIF loop. |
| 14 |
it2 = it2 + 1. Increments factor it2 ready for the next test. |
| 15 |
until flag = 0| it2 > 8. If flag is still TRUE and it2 hasn't exceed 8, the DO-LOOP is executed again. |
| 16 |
endif. Housekeeping - closes END-ENDIF loop. |
| 17 |
next it1. Takes the next value of it1 and continues executing the FOR-NEXT loop. |
| The
functions called by the main routine have all been used in previous
Puzzlets, and are just about
self-explanatory. If you
want to know more about them please either refer back, or e-mail me
directly. |
| When
you run the program, you'll see the inset printed out onto your
computer's screen. There are five solutions within the required range of integers and
factors, and the anagrams are all in evidence. |
|
Searching
... 1359 x 7 = 9513 1386 x 6 = 8316 1782 x 4 = 7128 2178 x 4 = 8712 2475 x 3 = 7425 No More! Press a key ... |