Code Golf:找到加权中位数的最短代码?

ily*_* n. 4 language-agnostic code-golf

我尝试打码打高尔夫球.

找到最小值?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;
Run Code Online (Sandbox Code Playgroud)

(实际上,当你看到变量isum重复使用时,它已经被大量优化)

规则

花车和整数:不同的语言有不同的浮点运算的标准,所以我重新制定问题都x[i]w[i]整数,你可以返回两次答案的值(这始终是整数),如果你喜欢.您可以返回,打印或分配变量的答案.

加权中位数和澄清的定义:

  • 排序x[i]的长度数组的中位数nx[n/2](x[n/2-1/2]+x[n/2+1/2])/2取决于n是奇数还是偶数
  • 未排序数组的中位数是排序后数组的中位数(true,但我们的数组已排序)
  • x[i]具有整数正权重的加权中值w[i]被定义为较大阵列的中值,其中每次出现x[i]都被改变为w[i]出现的次数x[i].

我希望看到什么

提出问题的原因之一是我认为最合适的语言将使用lambdas进行简单的数组求和和迭代.我认为功能语言可能是合理的,但我不确定 - 所以这是问题的一部分.我的希望是看到类似的东西

    // 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]
Run Code Online (Sandbox Code Playgroud)

Dunno,如果有任何语言,这是可能的,实际上更短.

测试数据

static int n = 10;
for (int j = 0; j < n; j++) {
        w[j] = j + 1;
        x[j] = j;
}
Run Code Online (Sandbox Code Playgroud)

答案: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;
}
Run Code Online (Sandbox Code Playgroud)

答案:6.5或13.

eph*_*ent 5

Ĵ

继续直接在解释器中输入.提示符是三个空格,因此缩进行是用户输入.

   m=:-:@+/@(((2*+/\)I.+/)"1@(,:(\:i.@#))@[{"0 1(,:(\:i.@#))@])
Run Code Online (Sandbox Code Playgroud)

我在其他答案中使用的测试数据:

   1 1 1 1 m 1 2 3 4
2.5
   1 1 2 1 m 1 2 3 4
3
   1 2 2 5 m 1 2 3 4
3.5
   1 2 2 6 m 1 2 3 4
4
Run Code Online (Sandbox Code Playgroud)

测试数据添加到问题中:

   (>:,:[)i.10
1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8  9
   (>:m[)i.10
6
   (([+<&6),:>:)i.9
1 2 3 4 5 6 6 7 8
1 2 3 4 5 6 7 8 9
   (([+<&6)m>:)i.9
6.5
Run Code Online (Sandbox Code Playgroud)
   i =: (2 * +/\) I. +/
Run Code Online (Sandbox Code Playgroud)

第一个指数使总和大于或等于累计和的两倍.

   j =: ,: (\: i.@#)
Run Code Online (Sandbox Code Playgroud)

列表及其反向.

   k =: i"1 @ j @ [
Run Code Online (Sandbox Code Playgroud)

第一个指数是- 见于左参数及其反转之上.

   l =: k {"(0 1) j @ ]
Run Code Online (Sandbox Code Playgroud)

这些索引分别从正确的参数及其反向中提取.

   m =: -: @ +/ @ l
Run Code Online (Sandbox Code Playgroud)

结果列表总和的一半.