' Puzzlet #034
' Find any 2 integers a and b such that
' a, b, and their product use all the
' digits 1 to 9 inclusive once and once
' only.
' Example: 42 x 138 = 5796.
' Find all other examples.
' By Dave Ellis.
declare MakeString(a: int, b: int, c: int)
declare NoZeroes(n$: string)
declare AllDigitsDifferent(d$: string)
declare printResult(a: int, b: int, c: int)
def i, j, k: int
def k$: string
openconsole
print "Searching ...": print
' find solutions of form n x nnnn = nnnn
for i = 2 to 8
for j = 1234 to 4987
k = i * j
if k < 9877
k$ = MakeString(i, j, k)
if NoZeroes(k$)
if AllDigitsDifferent(k$)
printResult(i, j, k)
endif
endif
endif
next j
next i
' find solutions of form nn x nnn = nnnn
for i = 12 to 80
for j = 123 to 823
k = i * j
if k < 9877
k$ = MakeString(i, j, k)
if NoZeroes(k$)
if AllDigitsDifferent(k$)
printResult(i, j, k)
endif
endif
endif
next j
next i
print: print "No more!"
print: print "Press a key to exit ... ",
do: until inkey$ <> ""
closeconsole
end
sub MakeString (a, b, c)
' takes 3 integers, converts them into
' strings, concatenates them, and returns
' the result as a single string
def a$, b$, c$, con$: string
a$ = ltrim$(str$(a))
b$ = ltrim$(str$(b))
c$ = ltrim$(str$(c))
con$ = a$ + b$ + c$
return con$
sub AllDigitsDifferent(d$)
' takes a 9-digit string as input. If all
' nine characters are unique, returns 1,
' otherwise returns 0.
def flag, it1, it2: int
flag = 1
it1 = 1
do
it2 = it1 + 1
do
it1$ = mid$(d$, it1, 1)
it2$ = mid$(d$, it2, 1)
if it1$ = it2$
flag = 0
endif
it2 = it2 + 1
until flag = 0 | it2 > 9
it1 = it1 + 1
until flag = 0 | it1 > 8
return flag
sub NoZeroes (n$)
' if the input string contains at least
' one zero, returns 0, otherwise returns 1
def flag, i: int
flag = 1
i = 1
do
if mid$(n$, i, 1) = "0"
flag = 0
endif
i = i + 1
until flag = 0 | i > 9
return flag
sub printResult(a, b, c)
' pretty printer
print using ("##", a),
print " x ",
print using ("####", b),
print " = ",
print c
return
PROGRAM NOTES
We're back to pandigitals again this month, but with a new twist. We're asked to fill in the values for the equation a * b = c. The difficult part is that the digits from a, b, and c between them have to make a pandigital number - that is, all the digits 1 to 9 have to appear once and once only.
Each part of the equation can have as few or as many digits as we wish, as long as the equation is correct, and a pandigital is formed. We were given the example: 12 x 483 = 5976.
The only other clue we have is that other solutions exist. So the Puzzlet is to find how many others, and what their details are.
It makes life a lot simpler if we can deduce the range to search before writing a program. Let's begin by looking at "a." Can it be as small as one digit? Yes, as long as it's not 1, since this would generate repeated digits, not allowed in our pandigital. If it were, say, 2, and b is, say, in the region of 3456, then c will be in the region of 7891, making a posible pandigital.
I know that, in this example, a * b is not equal to c, but the orders of magnitude are correct, so the program can commence its search in this range. Note that, when a is a single digit, b must be four digits so that c can also be four digits in length, making the total of nine digits required by the pandigital. We cannot allow a to be 1 because then b would equal c, and it would not form a pandigital number.
Can "a" be two digits in size? Once again, the answer is yes. If b were three digits, c could be four digits, potentially forming the required pandigital. Note that, in these circumstances, b cannot be four digits long, or c would be at least five digits, making eleven digits in all - too many for a pandigital.
We could make "a" three digits long, but then b would have to be two digits, and this would just repeat the solutions for a equals two digits and b equal three digits in reverse, so there's no point
in searching those combinations. This leaves us with the following to try:
1. n * nnnn = nnnnThe first part of the main routine deals with type 1, and the second part with type 2.
2. nn * nnn = nnnn.
To make the code notes simpler to follow, I've numbered the important lines from the main routine.
Line 1: variable i is set to search the range for part 1 solutions - that is, of the form n*nnnn = nnnn. As discussed above, i isn't allowed to be set to value 1.
1
2
3
4
5
6
7
8
9
0
11
12
13
for i = 2 to 8
for j = 1234 to 4987
k = i * j
if k < 9877
k$ = MakeString(i, j, k)
if NoZeroes(k$)
if AllDigitsDifferent(k$)
printResult(i, j, k)
endif
endif
endif
next j
next i
Line 2: variable j performs the search for the second muliplier. Its range is easy to understand. The minimum value is 1234, since that's the smallest possible 4-digit part of a pandigital. The maximum must be less than 5,000, since 2 x 5,000 = 10,000, an expression with 10 digits, one too many for our requirements. Thus, the greatest possible 4-digit value for the second multipler is 4987, which retains the property of having all different digits.
Line 3: variable k is loaded with the value found from the product of i and j.
Line 4: k's value is tested. If it's greater than 4 digits, there's no point in continuing, since, as explained above, the expression would end up being longer than 9 digits.
Line 5: if k passed the size test, it's turned into a string format, k$. This is because the next two tests can best be carried out on a string.
Line 6: k$ is passed to the function NoZeroes(), which tests for the presence of any zeroes. If k$ contains zeroes, it can't be a 9-digit pandigital, and 0 (FALSE) is returned, otherwise 1 (TRUE) is returned.
Line 7: all that remains is to ensure that all 9 digits of k$ are different, and the function AllDigitsDifferent() carries out this task, returning TRUE and FALSE as appropriate. The reason for carrying out the No Zeroes check first is that this is a relatively quick process, and many products actually fail at this point. The All Digits Different check is lengthier, so this arrangement improves efficiency.
Line 8: a TRUE from line 7 means we have a solution, and the PrintResult() subroutine is invoked to print it neatly.
The rest of the lines just close the IF-ENDIF and FOR-NEXT loops.
The whole process is repeated for type 2 expressions. It would be possible to automate this so that the same lines of code are used twice with the values in lines 1 and 2 being changed as appropriate. I decided not to do this simply to make things easier to understand, but I leave it to the more enthusiastic programmers to do as an exercise!
When you run the code, it will produce the inset screen.
There are thus nine solutions, only two of them being of type 1.
Searching ...
4 x 1738 = 6952
4 x 1963 = 7852
12 x 483 = 5796
18 x 297 = 5346
27 x 198 = 5346
28 x 157 = 4396
39 x 186 = 7254
42 x 138 = 5796
48 x 159 = 7632
No more!
Press a key to exit ...
MAIN MENU
DOWNLOAD CODE
ARCHIVES
Site design/maintenance: Dave Ellis E-mail me!
Last Updated: February 22nd, 2004.