计算中位数


32

挑战

给定一个非空的实数列表,请计算其中位数。

定义

中位数计算如下:首先对列表进行排序,

  • 如果条目数为奇数,则中位数为排序列表中心的值,
  • 否则,中位数是最接近排序列表中心的两个值的算术平均值。

例子

[1,2,3,4,5,6,7,8,9] -> 5
[1,4,3,2] -> 2.5
[1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,-5,100000,1.3,1.4] -> 1.5
[1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,-5,100000,1.3,1.4] -> 1.5

可以作为一个部分,我们输出超过200(例如, 7/28/2
小麦向导

根据这个分数很好。
瑕疵

15
这如何已经不是一个挑战?
orlp

1
@orlp这是此挑战的子集。
AdmBorkBork

3
由于存在一些有趣的线性时间算法,因此它也是一个很好的最快的代码挑战。

Answers:


18

Python 2,48个字节

返回结果的未命名函数。-1个字节感谢xnor。

lambda l:l.sort()or(l[len(l)/2]+l[~len(l)/2])/2.

显然,第一步是使用对数组进行排序l.sort()。但是,我们在lambda中只能有一个语句,因此我们利用了以下事实:sort函数None通过添加or- 来返回None,这在Python中是错误的,这告诉它评估并返回语句的下一部分。

现在我们有了排序列表,我们需要找到中间值或中间两个值。

使用条件检查长度的奇偶校验会太冗长,因此我们得到了索引len(l)/2~len(l)/2

  • 第一个是floor(length / 2),如果长度为奇数,则获取中间元素;如果长度为偶数,则获取中心对中的左侧元素。
  • 第二个是列表长度的二进制求反,计算结果为-1-floor(length / 2)。由于Python的负索引,它的作用与第一个索引基本相同,但从数组末尾开始。

如果列表的长度为奇数,则这些索引将指向相同的值。如果长度相等,则它们将指向中心的两个项目。

现在我们有了这两个索引,我们在列表中找到了这些值,将它们求和,然后将它们除以2。尾随的小数位/2.确保它是浮点除法而不是整数除法。

由于这是lambda函数,因此将隐式返回结果。

在线尝试!


尽管重复,但看起来lambda胜出了:lambda l:l.sort()or(l[len(l)/2]+l[~len(l)/2])/2.
xnor

@xnor谢谢!当我尝试这样做时,我不小心计算了f=,以为它长1个字节。
FlipTack

13

Python3 - 31 30个字节

感谢@Dennis,节省了一个字节!

我没有计划内置的答案,但是我找到了这个模块,并认为它真的很酷,因为我不知道它的存在。

from statistics import*;median

在这里在线尝试


6
from statistics import*;median保存一个字节。
丹尼斯,

@丹尼斯哦,太酷了。总是短吗?
Maltysen

2
它总是击败使用__import__,但import math;math.log会击败from math import*;log
丹尼斯,


9

果冻,9字节

L‘HịṢµ÷LS

在线尝试!

说明

我仍然无法掌握Jelly的知识……我无法为列表的中位数或均值找到内建函数,但是对于Jelly允许将非整数索引纳入列表这一挑战非常方便,在这种情况下,它将返回两个最接近的值对。这意味着我们可以将输入长度的一半用作索引,并在需要平均时获得一对值。

L          Get the length of the input.
 ‘         Increment it.
  H        Halve it. This gives us the index of the median for an odd-length list
           (Jelly uses 1-based indexing), and a half-integer between the two indices
           we need to average for even-length lists.
   ịṢ      Use this as an index into the sorted input. As explained above this will
           either give us the median (in case of an odd-length list) or a pair of
           values we'll now need to average.
     µ     Starts a monadic chain which is then applied to this median or pair...
      ÷L     Divide by the length. L treats atomic values like singleton lists.
        S    Sum. This also treats atomic values like singleton lists. Hence this
             monadic chain leaves a single value unchanged but will return the
             mean of a pair.

当然,Æṁ现在可以使用
Caird coinheringaahing

9

Brain-Flak,914 + 1 = 915字节

([]){({}[()]<(([])<{({}[()]<([([({}<(({})<>)<>>)<><({}<>)>]{}<(())>)](<>)){({}())<>}{}({}<><{}{}>){{}<>(<({}<({}<>)<>>)<>({}<>)>)}{}({}<>)<>>)}{}<>{}>[()]){({}[()]<({}<>)<>>)}{}<>>)}{}([]<(()())>(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{}<(())>){((<{}{}([[]]()){({}()()<{}>)}{}(({}){}<([]){{}{}([])}{}>)>))}{}{(<{}([[]]()()){({}()()<{}>)}{}({}{}<([]){{}{}([])}{}>)>)}{}([(({}<((((((()()()){}){}){}()){})[()()()])>)<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}(({}<>)<{(<{}([{}])>)}{}{(({})<((()()()()()){})>)({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{})({}<({}<>)<>>((((()()()){}){}){}){})((()()()()()){})<>({}<>)(()()){({}[()]<([([({})](<()>))](<>())){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}(({})<>)<>{(<{}([{}])>)}{}({}<>)<>({}<><({}<>)>)>)}{}({}(<>))<>([()]{()<(({})){({}[()])<>}{}>}{}<><{}{}>)<>(({}{}[(())])){{}{}(((<{}>)))}{}{}{(<{}<>([{}])><>)}{}<>}{}>){(<{}(((((()()()()())){}{})){}{})>)}{}

需要该-A标志才能运行。

在线尝试!

说明

该算法的核心是我前一段时间写的冒泡排序。

([]){({}[()]<(([])<{({}[()]<([([({}<(({})<>)<>>)<><({}<>)>]{}<(())>)](<>)){({}())<>}{}({}<><{}{}>){{}<>(<({}<({}<>)<>>)<>({}<>)>)}{}({}<>)<>>)}{}<>{}>[()]){({}[()]<({}<>)<>>)}{}<>>)}{}

我不记得它是如何工作的,所以不要问我。但是我确实知道它可以对堆栈进行排序,甚至可以处理负片

在对所有内容进行排序之后,我发现以下内容是中位数的2倍

([]<(()())>(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{}<(())>)  #Stack height modulo 2
{((<{}{}          #If odd
 ([[]]())         #Push negative stack height +1
 {                #Until zero 
  ({}()()<{}>)    #add 2 to the stack height and pop one
 }{}              #Get rid of garbage
 (({}){}<         #Pickup and double the top value
 ([]){{}{}([])}{} #Remove everything on the stack
 >)               #Put it back down
>))}{}            #End if
{(<{}                     #If even
  ([[]]()())              #Push -sh + 2
  {({}()()<{}>)}{}        #Remove one value for every 2 in that value
  ({}{}<([]){{}{}([])}{}>)#Add the top two and remove everything under them
>)}{}                     #End if

现在剩下的就是将其转换为ASCII

([(({}<((((((()()()){}){}){}()){})[()()()])>)<(())>)](<>)){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}(({}<>)<
{(<{}([{}])>)}{}  #Absolute value (put "/2" beneath everything)

{                 #Until the residue is zero 
(({})<            #|Convert to base 10
((()()()()()){})  #|
>)                #|...
({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]{})
({}<({}<>)<>>((((()()()){}){}){}){})((()()()()()){})<>({}<>)
                  #|
(()()){({}[()]<([([({})](<()>))](<>())){({}())<>}{}<>{}{}<>(({})){{}{}<>(<(())>)}{}(({})<>)<>{(<{}([{}])>)}{}({}<>)<>({}<><({}<>)>)>)}{}({}(<>))<>([()]{()<(({})){({}[()])<>}{}>}{}<><{}{}>)<>(({}{}[(())])){{}{}(((<{}>)))}{}{}{(<{}<>([{}])><>)}{}<>
}{}               #|
>)
{(<{}(((((()()()()())){}{})){}{})>)}{}  #If it was negative put a minus sign

7

R,6个字节

median

不足为奇的是R,一种统计编程语言,具有此内置功能。


4
R击败果冻:D:D:D
JAD



5

八度,38字节

@(x)mean(([1;1]*sort(x))(end/2+[0 1]))

这定义了一个匿名函数。输入是行向量。

在线尝试!

说明

            sort(x)                 % Sort input x, of length k
      [1;1]*                        % Matrix-multiply by column vector of two ones
                                    % This vertically concatenates the sort(x) with 
                                    % itself. In column-major order, this effectively 
                                    % repeats each entry of sort(x)
     (             )(end/2+[0 1])   % Select the entry at position end/2 and the next.
                                    % Entries are indexed in column-major order. Since
                                    % the array has 2*k elements, this picks the k-th 
                                    % and (k+1)-th. Because entries were repeated, for
                                    % odd k this takes the original (k+1)/2-th entry
                                    % (1-based indexing) twice. For even k this takes
                                    % the original (k/2)-th and (k/2+1)-th entries
mean(                            )  % Mean of the two selected entries

1
......巧妙地使用bsxfun“和mean:-)
Stewie Griffin

5

JavaScript,57 52字节

v=>(v.sort((a,b)=>a-b)[(x=v.length)>>1]+v[--x>>1])/2

对数组进行数字排序。如果数组是偶数长度,请找到2个中间数字并将其取平均值。如果数组为奇数,请找到中间数字两次并除以2。


1
我发现Array.sort()使用小数点无法正常工作
TrojanByAccident

3
如果您像我一样传递排序功能,它也会这样做。如果不带任何参数调用Array.sort(),它将使用字母排序。
Grax32

有趣。不知道
TrojanByAccident

您可以通过sort()直接使用返回值并删除t变量来节省一些字节:v=>(v.sort((a,b)=>a-b)[(x=v.length)>>1]+v[--x>>1])/2
Arnauld

1
并不是您必须对此进行更正,但是,如果x>=2**31这样做将失败。>>是一个正负号传播的右移,这意味着当数字解释为32位整数时,如果设置了msb,则它将保持设置状态,从而使的结果为负2**32>x>=2**31。因为x>=2**32,它只是屈服0
帕特里克·罗伯茨

5

Matlab / Octave,6个字节

无聊的内置:

median

在线尝试!


我忘记了MATLAB / Octave中匿名函数的规则,这应该是@median吗?
朱塞佩

@Giuseppe我不知道当前对内置函数评分的方法是什么。
瑕疵的

4

Mathematica,6个字节

Median

一旦找出Mthmtca,我就会在其中发布解决方案。


在Mthmtca 0.1 / 10.1.0.0中,代码将具有字节CBC8ËÈ)。但是,在我应用另一个补丁之前,函数调用的概念可能不符合PPCG的标准。
LegionMammal978 '17

4

Perl 6,31个字节

*.sort[{($/=$_/2),$/-.5}].sum/2

试试吧

展开:

*\     # WhateverCode lambda ( this is the parameter )

.sort\ # sort it

[{     # index into the sorted list using a code ref to calculate the positions

  (
    $/ = $_ / 2 # the count of elements divided by 2 stored in 「$/」
  ),            # that was the first index

  $/ - .5       # subtract 1/2 to get the second index

                # indexing operations round down to nearest Int
                # so both are effectively the same index if given
                # an odd length array

}]\

.sum / 2        # get the average of the two values


4

APL(Dyalog Unicode),14个字节

≢⊃2+/2/⊂∘⍋⌷÷∘2

在线尝试!

这是火车。原始dfn是{(2+/2/⍵[⍋⍵])[≢⍵]÷2}

火车的结构如下

┌─┼───┐
  ┌─┼───┐
    2 / ┌─┼───┐
    ┌─┘ 2 / ┌─┼─┐
    +         
           ┌┴┐ ┌┴┐
             ÷ 2

表示正确的参数。

指数

  • ⊂∘⍋索引成索引的结果被排序

  • ÷∘2分为二

2/复制两次,因此1 5 7 8成为1 1 5 5 7 7 8 8

2+/ 取成对和,这变成 (1+1)(1+5)(5+5)(5+7)(7+7)(7+8)(8+8)

从这个选择

  • 索引长度等于的元素

先前的解决方案

{.5×+/(⍵[⍋⍵])[(⌈,⌊).5×1+≢⍵]}
{+/(2/⍵[⍋⍵]÷2)[0 1+≢⍵]}
{+/¯2↑(1-≢⍵)↓2/⍵[⍋⍵]÷2}
{(2+/2/⍵[⍋⍵])[≢⍵]÷2}
{(≢⍵)⊃2+/2/⍵[⍋⍵]÷2}
≢⊃2+/2/2÷⍨⊂∘⍋⌷⊢
≢⊃2+/2/⊂∘⍋⌷÷∘2

3

普通Lisp 89

(lambda(s &aux(m(1-(length s)))(s(sort s'<)))(/(+(nth(floor m 2)s)(nth(ceiling m 2)s))2))

我计算位置(floor middle)和的元素的平均值(ceiling middle),其中middle是排序列表中间元素的从零开始的索引。这是可能的middle是一个整数,如1尺寸为3如的输入列表中(10 20 30),或对于列表的元素,等的偶数分数3/2(10 20 30 40)。在这两种情况下,我们都计算期望的中值。

(lambda (list &aux
             (m (1-(length list)))
             (list (sort list #'<)))
  (/ (+ (nth (floor m 2) list)
        (nth (ceiling m 2) list))
     2))

3

Vim,62个字节

我最初在V语言中仅使用文本操作来完成此操作,直到最后,但对处理[X]和[X,Y]感到沮丧,因此这是简单的版本。它们的长度大致相同。

c$:let m=sort(")[(len(")-1)/2:len(")/2]
=(m[0]+m[-1])/2.0

在线尝试!

无法打印的内容:

c$^O:let m=sort(^R")[(len(^R")-1)/2:len(^R")/2]
^R=(m[0]+m[-1])/2.0

荣誉提名:

  • ^O 使您退出一个命令(let命令)的插入模式。
  • ^R" 插入被拉动的文本(在这种情况下为列表)

3

TI基本,2字节

median(Ans

非常简单。


2
Ans不是允许的I / O方法
Mego

1
@Mego您的链接和评论使我感到困惑...根据投票,这允许的。我想念什么吗?
Patrick Roberts

@PatrickRoberts实际上,关于可接受性的门槛目前存在一些争论。几个用户(包括我自己)一直遵循这样的规则,即一种方法至少需要+5倍的投票数,并且至少是向下投票数的两倍。用于标准漏洞。
Mego

谁从我自己的帖子中两次删除了我的评论,都会很烦人。由于没有关于可接受性的明确接受规则,因此我在这里看不到问题。您可以在SO上看到我的答案,以了解如何将其用作程序的参数。
Timtech '17

@Mego +38更加-18的两倍
Timtech

3

C#,126个字节

using System.Linq;float m(float[] a){var x=a.Length;return a.OrderBy(g=>g).Skip(x/2-(x%2==0?1:0)).Take(x%2==0?2:1).Average();}

非常简单,这里使用LINQ对值进行排序,跳过列表的一半,根据偶数/奇数取一或两个值并将它们取平均值。


您需要将其包括using System.Linq; 在字节数中,但是您可以通过进行一些更改将其取消。编译为a Func<float[], float>并将取模的值分配给一个106字节的变量:using System.Linq;a=>{int x=a.Length,m=x%2<1?1:0;return a.OrderBy(g=>g).Skip(x/2-m).Take(++m).Average();};
TheLethalCoder

@TheLethalCoder我不太确定什么构成一个完整的程序。你是正确的使用。将模数的声明与长度连接起来也是一个好主意。我对此进行了一些试验,但无法使它短于两次。我敢说您的优化本身值得一个答案,因为它们是相当实质的,我不会提出它们。
詹斯(Jens)

挑战并没有说明您需要完整的程序,因此可以使用匿名方法。除此之外,我只说了一些常见的打高尔夫球技巧,因此我无需添加答案就可以自己打高尔夫球!
TheLethalCoder

3

C ++ 112字节

感谢@ original.legin帮助我节省了字节。

#include<vector>
#include<algorithm>
float a(float*b,int s){std::sort(b,b+s);return(b[s/2-(s&1^1)]+b[s/2])/2;}

用法:

    int main()
    {
        int n = 4;
        float e[4] = {1,4,3,2};
        std::cout<<a(e,n); /// Prints 2.5

        n = 9;
        float e1[9] = {1,2,3,4,5,6,7,8,9};
        std::cout<<a(e1,n); /// Prints 5

        n = 13;
        float e2[13] = {1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,-5,100000,1.3,1.4};
        std::cout<<a(e2,n); /// Prints 1.5

        return 0;
    }

1
您可以使用float而不是double保存两个字节。另外,在GCC上,您可以使用#import<vector>#import<algorithm>代替#include。(请注意,您无需在#include或后面加上空格#import
Steadybox

@Steadybox我没有计算分数中包括的两个。我是不是该?另外,我主要使用Clang,所以我对GCC不太了解,但谢谢。
韦德·泰勒

是的,如果代码没有它们就不能编译,则包含应该包含在字节数中。
Steadybox'1

3

J16 14字节

2%~#{2#/:~+\:~

在线尝试!

除了BMO的阵列复制技巧外,我发现我们可以添加按两个方向排序的整个阵列。然后我意识到可以颠倒这两个步骤,即添加两个数组,然后复制它们并采用nth元素。

怎么运行的

2%~#{2#/:~+\:~
                Input: array of length n
       /:~      Sort ascending
           \:~  Sort descending
          +     Add the two element-wise
     2#         Duplicate each element
   #{           Take n-th element
2%~             Halve

先前的答案

stats附件的J,18个字节

load'stats'
median

在线尝试!

库功能FTW。

median的实现如下所示:

J,31个字节

-:@(+/)@((<.,>.)@(-:@<:@#){/:~)

在线尝试!

怎么运行的

-:@(+/)@((<.,>.)@(-:@<:@#){/:~)
         (<.,>.)@(-:@<:@#)       Find center indices:
                  -:@<:@#          Compute half of given array's length - 1
          <.,>.                    Form 2-element array of its floor and ceiling
                          {/:~   Extract elements at those indices from sorted array
-:@(+/)                          Sum and half

打高尔夫球可以达到以下目的:

J,28个字节

2%~[:+/(<.,>.)@(-:@<:@#){/:~

在线尝试!


1
做得很好,我的APL答案的J端口将#{0,2+/\2#-:/:]接近15个字节(我想念的人⎕io)。
Kritixi Lithos

2

J,19个字节

<.@-:@#{(/:-:@+\:)~

说明:

        (        )~   apply monadic argument twice to dyadic function 
         /:           /:~ = sort the list upwards
               \:     \:~ = sort the list downwards
           -:@+       half of sum of both lists, element-wise
<.@-:@#               floor of half of length of list
       {              get that element from the list of sums

您可以通过删除括号和应用节省一个字节~直接给每个<.@-:@#{/:~-:@+\:~
英里

2

JavaScript,273字节

function m(l){a=(function(){i=l;o=[];while(i.length){p1=i[0];p2=0;for(a=0;a<i.length;a++)if(i[a]<p1){p1=i[a];p2=a}o.push(p1);i[p2]=i[i.length-1];i.pop()}return o})();return a.length%2==1?l[Math.round(l.length/2)-1]:(l[Math.round(l.length/2)-1]+l[Math.round(l.length/2)])/2}

2

Java 7,99个字节

打高尔夫球:

float m(Float[]a){java.util.Arrays.sort(a);int l=a.length;return l%2>0?a[l/2]:(a[l/2-1]+a[l/2])/2;}

取消高尔夫:

float m(Float[] a)
{
    java.util.Arrays.sort(a);
    int l = a.length;
    return l % 2 > 0 ? a[l / 2] : (a[l / 2 - 1] + a[l / 2]) / 2;
}

在线尝试


即使Java 7的排序语法不够短,en.wikipedia.org
wiki /…也不

您不需要计算进口额java.util.Arrays吗?
FlipTack

糟糕,感谢您的通知。:)
peech '17

你好,未来!通过使用整数除法截断来处理长度奇偶校验,可以节省14个字节。请参阅我的Java 8答案
雅各布

2

Pari / GP-37 39字节

a为包含值的行向量。

b=vecsort(a);n=#b+1;(b[n\2]+b[n-n\2])/2  \\ 39 byte              

n=1+#b=vecsort(a);(b[n\2]+b[n-n\2])/2    \\ obfuscated but only 37 byte

由于Pari / GP是交互式的,因此不需要其他命令即可显示结果。


对于“尝试在线”链接,添加了之前和之后的一行。为了进行打印,将中位数结果存储在变量w中

a=vector(8,r,random(999))           
n=1+#b=vecsort(a);w=(b[n\2]+b[n-n\2])/2      
print(a);print(b);print(w)       

在线尝试!


2

Japt,20个字节

n gV=0|½*Ul)+Ug~V)/2

在线测试!Japt确实缺少必要的内置工具来为这个挑战创建一个简短的答案...

说明

n gV=0|½*Ul)+Ug~V)/2  // Implicit: U = input list
n                     // Sort U.
   V=0|½*Ul)          // Set variable V to floor(U.length / 2).
  g                   // Get the item at index V in U.
            +Ug~V     // Add to that the item at index -V - 1 in U.
                 )/2  // Divide by 2 to give the median.
                      // Implicit: output result of last expression

2

Java 8,71字节

平价很有趣!这是从double[]到的Lambda Double

l->{java.util.Arrays.sort(l);int s=l.length;return(l[s/2]+l[--s/2])/2;}

这里没有什么复杂的事情。对数组进行排序,然后从数组中取两个数字的平均值。有两种情况:

  • 如果长度为偶数,则第一个数字从数组中间的正前方获取,第二个数字从整数之前的位置获取。这些数字的平均值是输入的中位数。
  • 如果长度为奇数,s并且s-1两个除法到中间元件的索引。该数字加到自身上,结果除以二,得出原始值。

在线试用


2

SmileBASIC,45字节

DEF M A
L=LEN(A)/2SORT A?(A[L-.5]+A[L])/2
END

获取floor(length / 2)和floor(length / 2-0.5)的元素的平均值,非常简单,但是通过移动内容,我能够节省1个字节:

DEF M A
SORT A    <- extra line break
L=LEN(A)/2?(A[L-.5]+A[L])/2
END

2

外壳,10个字节

½ΣF~e→←½OD

在线尝试!

说明

[a1aN][a1a1aNaN]

½ΣF~e→←½OD  -- example input: [2,3,4,1]
         D  -- duplicate: [2,3,4,1,2,3,4,1]
        O   -- sort: [1,1,2,2,3,3,4,4]
       ½    -- halve: [[1,1,2,2],[3,3,4,4]]
  F         -- fold the following
   ~        -- | compose the arguments ..
     →      -- | | last element: 2
      ←     -- | | first element: 3
    e       -- | .. and create list: [2,3]
            -- : [2,3]
 Σ          -- sum: 5
½           -- halve: 5/2

不幸的是½for列表具有类型[a] -> [[a]][a] -> ([a],[a])而不是不允许的,F~+→←因为foldl1需要将类型的功能a -> a -> a作为第一个参数,迫使我使用e



2

GolfScript27 25 20 17字节

~..+$\,(>2<~+"/2"

将输入作为标准输入上的整数数组。输出为未缩减的分数。在线尝试!

说明

ll1l

~                  Evaluate input (converting string -> array)
 ..                Duplicate twice
   +               Concatenate two of the copies
    $              Sort the doubled array
     \,            Swap with the non-doubled array and get its length: l
       (           Decrement: l-1
        >          Array slice: all elements at index (l-1) and greater
         2<        Array slice: first two elements (originally at indices l-1 and l)
           ~       Dump array elements to stack
            +      Add
             "/2"  Push that string
                   Output all items on stack without separator

输出将类似于10/2

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.