Multiplication: Finding the Greatest Product
fawnnguyen.com
fawnnguyen.com
def maximize_product(m, n, digits):
if m < 1 or n < 1 or m + n != len(digits):
raise Exception
flipped = m > n
if flipped:
m, n = n, m
digits = sorted(digits)
a, b = [], []
while len(a) < m:
a.append(digits.pop())
b.append(digits.pop())
if a[-1] != b[-1]:
break
while len(a) < m:
b.append(digits.pop())
a.append(digits.pop())
while len(b) < n:
b.append(digits.pop())
if flipped:
a, b = b, a
return a, b
print maximize_product(3, 2, [8, 4, 2, 7, 5])
I think I have a proof that it gives the right answer, but won't spell it out here. def best_digit_choice_to_maximize_product(n, digits):
numer = lambda d: reduce(
sorted(d, reverse=True),
0,
lambda a, e: a*10 + e)
return max(
itertools.combinations(digits, n),
key = lambda e: numer(e) * numer(set(digits) - set(e)))(BTW, I just realized that my code can be made O(n), by replacing the default sort with a counting sort :-))
Two fixes: - If you use `(Counter(digits)-Counter(e)).elements()` in the last line, you can support repeated digits. - Reduce is `reduce(function, sequence[, initial]) -> value` so you should move the lambda to the first argument.
All in all I think this is a very nice, succinct use of Python. The combinatorial parts of `itertools` are extreamly handy :)
Once you figure out that the most significant digits should be the largest ones, and the 3rd and 4th largest digits should be in the 2nd most significant place, you end up with a situation like this:
A C E
* B D
To make it more clear what to do next, you can just append a zero onto the number "BD" and still solve the same problem, because instead of multiplying "ACE" * "BD", you are multiplying "ACE" * "BD0" = ("ACE" * "BD") * 10: A C E
* B D 0
Now, to figure out which of the two greatest digits are A and B, and which of the next two greatest are C and D, you can apply the identity (x + y) * (x - y) = x^2 - y^2 to this. Since "ABC" * "BD0" = (x + y) * (x - y), then equating "ABC" = x + y and "BD0" = x - y, you can solve to get x = ("ACE" + "BD0") / 2, which is the same number no matter the order between A and B, or between C and D. Then maximizing (x + y) * (x - y) means minimizing y^2; or, making the two numbers "ACE" and "BD0" as close together as possible, which leads to the given solution.