Minimum Scalar Product
August 10, 2012
Today’s exercise comes to us from the practice round of Google Code Jam 2008.
You are given two vectors v1=(x1,x2,…,xn) and v2=(y1,y2,…,yn). The scalar product of these vectors is a single number, calculated as x1y1+x2y2+…+xnyn.
Suppose you are allowed to permute the coordinates of each vector as you wish. Choose two permutations such that the scalar product of your two new vectors is the smallest possible, and output that minimum scalar product.
Google gives two examples: the minimum scalar product of the two vectors (1 3 -5) and (-2 4 1) is -25, and the minimum scalar product of the two vectors (1 2 3 4 5) and (1 0 1 0 1) is 6.
Your task is to write a program that finds the minimum scalar product of two vectors. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
My Haskell solution (see http://bonsaicode.wordpress.com/2012/08/10/programming-praxis-minimum-scalar-product/ for a version with comments):
[…] Pages: 1 2 […]
Is there a simple proof of the assertion that this always works? I looked briefly but failed to find one on the web and I need to attend to other things. I did find some other pages that simply assert that this pair of permutations produces the minimum. I found a purported counter-example that failed to be a counter-example. And I wrote a test program, below, that seems to confirm the assertion by always returning an empty set of permutations (of the second vector) that produce an even smaller result. So I believe it but if there is a memorable proof, I’d like to know.
It’s not a proof, but a simple observation is that the maximum scalar product is produced by multiplying the largest item from each vector, then the second largest, and so on; then the minimum scalar product is the opposite. I’ll ask at a couple of web sites I know.
perl6 version
Here's an attempt at a proof:
Consider two vectors:
A = <a_1, a_2, ..., a_n> sorted highest to lowest, so a_i >= a_j if i < j; and
B = <b_1, b_2, ..., b_n> sorted lowest to highest, so b_i <= b_j if i < j.
The scalar product (A dot B) of these two vectors is:
a_1*b_1 + a_2*b_2 + ... + a_i*b_i + ...
Assume there exist a B' in which the positions of b_i and b_j have been
exchanged so that:
A dot B' < A dot B
... + a_i*b_j + ... + a_j*b_i + ... < ... + a_i*b_i + ... + a_j*b_j + ...
all the terms in the '...' are the same on both sides, so this reduces to:
a_i*b_j + a_j*b_i < a_i*b_i + a_j*b_j
which can be rearranged:
a_i*(b_j - b_i) < a_j*(b_j - b_i)
By definition of B, b_i <= b_j for i < j.
If b_i == b_j, then B' == B, and (A dot B') == (A dot B).
If b_i < b_j, then (b_j - b_i) > 0, so:
a_i < a_j
This contradicts that A is sorted so that a_i >= a_j for i < j.
Therefore, the assumption must be false.
[…] today’s Programming Praxis exercise, our goal is to calculate the minimum scalar product of two vectors. […]
My Python solution:
def min_scalar_product(v1, v2):
return sum([x * y for x, y in zip(sorted(v1), sorted(v2, reverse=True))])
Min Scalar Product
My try in Common lisp
I asked at http://www.reddit.com/r/math/comments/xzsi8/minimum_scalar_product/ and got this answer from Luonos. I think that’s pretty much the same as Mike’s proof.
Requires -std=c++0x option when compiled with g++.
A Go solution:
[…] Another post from Programming Praxis, this time we’re to figure out what is the minimum scalar product of two vectors. Basically, you want to rearrange two given lists a1, a2, …, an and b1, b2, …, bn such that a1b1 + a2b2 + … + anbn is minimized. […]