我尝试打代码打高尔夫球。
找到 的最小值∑W_i*|X-X_i|
的问题减少到找到权重列表的加权中位数x[i]
(w[i]
定义见下文)。你将如何用一个最短、最简单、最漂亮的程序来做到这一点?
这是我的代码最初的样子(解释在问题的答案中,简短版本作为下面的答案之一发布)。
#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;
i
(实际上,当您看到变量并重用时,它已经被大量优化sum
)
规则
浮点数和整数:不同的语言有不同的浮点算术标准,所以我将问题重新表述为整数,x[i]
如果你愿意,你可以返回两倍的答案值(总是整数)。您可以返回、打印或将答案分配给变量。w[i]
加权中位数的定义和说明:
x[i]
长度排序数组的中位数n
是x[n/2]
或(x[n/2-1/2]+x[n/2+1/2])/2
取决于n
是奇数还是偶数未排序数组的中位数是排序后数组的中位数(是的,但我们的数组已排序)x[i]
具有整数正权重的加权中位数w[i]
定义为较大数组的中位数,其中每次出现的x[i]
都已更改为w[i]
的出现x[i]
。
我希望看到什么
询问的原因之一是我假设最合适的语言将使用 lambda 进行简单的数组求和和迭代。我认为函数式语言可能是合理的,但我不确定——所以这是问题的一部分。我希望看到类似的东西
// 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]
不知道是否有任何语言可以实现并且实际上更短。
测试数据
static int n = 10;
for (int j = 0; j < n; j++) {
w[j] = j + 1;
x[j] = j;
}
答案:6 或 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;
}
答案:6.5 或 13。