My try at code golfing.
The problem of finding the minimum value of ∑W_i*|X-X_i|
reduces to finding the weighted median of a list of x[i]
with weights w[i]
(see below for definition). How will you do that with a shortest, simplest and most beautiful program?
Here's how my code looked originally (explanation is in the answer to the question and short version is posted as one of the answers below).
#define zero(x) ( abs(x) < 1e-10 ) /* because == doesn't work for floats */
float sum = 0;
int i;
for (i = 0; i < n; i++)
sum += w[i];
while (sum > 0)
sum -= 2*w[--i];
right = x[i] // the rightmost minimum point
left = ( zero(sum) && zero(w[i]-w[i-1]) ) ? x[i-1] : right;
answer = (left + right) / 2;
(Actually, it's been already heavily optimized as you see variables i
and sum
reused)
Rules
Floats and integers: different languages have different floating point arithmetic standards, so I reformulate the problem to have x[i]
and w[i]
to be integers and you can return twice the value of the answer (which is always integer) if you prefer. You can return, print or assign the answer to variable.
Definition of weighted median and clarifications:
- Median of sorted array
x[i]
of lengthn
is eitherx[n/2]
or(x[n/2-1/2]+x[n/2+1/2])/2
depending on whethern
is odd or even Median of unsorted array is the median of array after sort(true, but our array is sorted)- Weighted median of
x[i]
with integer positive weightsw[i]
is defined as the median of larger array where each occurrence ofx[i]
has been changed intow[i]
occurrences ofx[i]
.
What I hope to see
One of the reasons for asking is that I assume the most suitable language will have trivial array summation and iteration with lambdas. I thought a functional language could be reasonable, but I'm not sure about that - so it's part of the question. My hope is to see something like
// standard function add := (a,b) :-> a + b
myreduce := w.reduce
with: add
until: (value) :-> 2*value >= (w.reduce with:add)
answer = x [myreduce from:Begin] + x [myreduce from:End]
Dunno if there's any language where this is possible and is actually shorter.
Test data
static int n = 10;
for (int j = 0; j < n; j++) {
w[j] = j + 1;
x[j] = j;
}
Answer: 6 or 12.
static int n = 9;
int w[n], x[n] ;
for (int j = 0; j < n; j++) {
w[j] = j + ((j<6) ? 1 : 0);
x[j] = j + 1;
}
Answer: 6.5 or 13.