辛普森多样性指数


19

辛普森指数是重复项的集合的多样性的措施。这只是在随机抽取而未均匀替换的情况下抽取两个不同项目的可能性。

对于相同项目n组中的n_1, ..., n_k项目,两个不同项目的概率为

$$ 1- \ sum_ {i = 1} ^ k \ frac {n_i(n_i-1)} {n(n -1)} $$

例如,如果您有3个苹果,2个香蕉和1个胡萝卜,则多样性指数为

D = 1 - (6 + 2 + 0)/30 = 0.7333

或者,不同项目的无序对的数量3*2 + 3*1 + 2*1 = 11总共为15对,并且11/15 = 0.7333

输入:

一串字符AZ。或者,此类字符的列表。它的长度至少为2。您可能不认为它是要排序的。

输出:

该字符串中字符的辛普森分集指数,即,随机替换产生的两个字符的概率不同。这是介于0和1之间(含0和1)的数字。

输出浮点数时,请至少显示4位数字,尽管要终止诸如1or 1.00.375OK之类的精确输出。

您不能使用专门计算多样性指数或熵测度的内置函数。只要您对测试用例有足够的准确性,则可以进行实际的随机抽样。

测试用例

AAABBC 0.73333
ACBABA 0.73333
WWW 0.0
CODE 1.0
PROGRAMMING 0.94545

排行榜

这是马丁·布特纳(MartinBüttner)提供的按语言排行榜。

为确保您的答案显示出来,请使用以下Markdown模板以标题开头。

# Language Name, N bytes

N您提交的文件大小在哪里。如果您提高了分数,则可以通过打败旧分数保持标题。例如:

# Ruby, <s>104</s> <s>101</s> 96 bytes


您正在使用Gini-Simpson索引,这是更好的度量方法,即反Simpson索引又称有效类型数。
Joe Z.

1
基本上1/代替1-。[业余统计员大声疾呼]
Joe Z.

Answers:


5

Python 2,72

输入可以是字符串或列表。

def f(s):l=len(s);return sum(s[i%l]<>s[i/l]for i in range(l*l))/(l-1.)/l

我已经知道在Python 3中它将短2个字节,所以请不要告诉我:)


<>位置36 的尖括号在做什么?我以前从未见过这种语法。
ApproachingDarknessFish

@TuttiFruttiJacuzzi:这是的同义词!=
RemcoGerlich 2015年


@ Vioz-不能与l=len(s);在那里
SP3000

@ Sp3000是的,没有注意到它被使用了多少次。
卡德,2015年

4

Pyth- 19 13 12 11字节

感谢@isaacg告诉我有关n的信息

使用带有.c组合功能的暴力破解方法。

csnMK.cz2lK

在这里在线尝试

测试套件

c                Float division
 s               Sum (works with True and False)
  nM             Map uniqueness
   K             Assign value to K and use value
    .c 2         Combinations of length 2
      z          Of input
 lK              Length of K

您可以替换.{n-它们在这里等效。
isaacg 2015年

@isaacg哦,不知道它会自动弹起,太酷了。
马蒂森(Maltysen)

4

SQL(PostgreSQL),182字节

作为postgres中的功能。

CREATE FUNCTION F(TEXT)RETURNS NUMERIC AS'SELECT 1-sum(d*(d-1))/(sum(d)*(sum(d)-1))FROM(SELECT COUNT(*)d FROM(SELECT*FROM regexp_split_to_table($1,''''))I(S)GROUP BY S)A'LANGUAGE SQL

说明

CREATE FUNCTION F(TEXT) -- Create function f taking text parameter
RETURNS NUMERIC         -- declare return type
AS'                     -- return definition
    SELECT 1-sum(d*(d-1))/(sum(d)*(sum(d)-1)) -- Calculate simpson index
    FROM(
        SELECT COUNT(*)d  -- Count occurrences of each character
        FROM(             -- Split the string into characters
            SELECT*FROM regexp_split_to_table($1,'''')
            )I(S)
        GROUP BY S        -- group on the characters
        )A 
'
LANGUAGE SQL

用法和测试运行

SELECT S, F(S)
FROM (
    VALUES
    ('AAABBC'),
    ('ACBABA'),
    ('WWW'),
    ('CODE'),
    ('PROGRAMMING')
   )I(S)

S              F
-------------- -----------------------
AAABBC         0.73333333333333333333
ACBABA         0.73333333333333333333
WWW            0.00000000000000000000
CODE           1.00000000000000000000
PROGRAMMING    0.94545454545454545455

4

J,26个字节

1-+/((#&:>@</.~)%&(<:*])#)

最酷的部分

我找到了每个字符的数量,方法是</.将字符串相对于自己(~反身),然后对每个框的字母进行计数。


1
(#&:>@</.~)可以(#/.~)并且(<:*])可以(*<:)。如果您使用适当的功能,则会得到(1-(#/.~)+/@:%&(*<:)#)。由于此处通常不计算周围的括号(leave 1-(#/.~)+/@:%&(*<:)#,函数的主体),因此会产生20个字节。
randomra

4

Python 3,66 58字节

这是使用问题中提供的简单计数公式,没有什么太复杂的。这是一个匿名的lambda函数,因此要使用它,您需要为其命名。

由于Sp3000,节省了8个字节(!)。

lambda s:1-sum(x-1for x in map(s.count,s))/len(s)/~-len(s)

用法:

>>> f=lambda s:1-sum(x-1for x in map(s.count,s))/len(s)/~-len(s)
>>> f("PROGRAMMING")
0.945454

要么

>>> (lambda s:1-sum(x-1for x in map(s.count,s))/len(s)/~-len(s))("PROGRAMMING")
0.945454

3

APL,39 36字节

{n←{≢⍵}⌸⍵⋄N←≢⍵⋄1-(N-⍨N×N)÷⍨+/n-⍨n×n}

这将创建一个未命名的monad。

{
  n ← {≢⍵}⌸⍵               ⍝ Number of occurrences of each letter
  N ← ≢⍵                   ⍝ Number of characters in the input
  1-(N-⍨N×N)÷⍨+/n-⍨n×n     ⍝ Return 1 - sum((n*n-n)/(N*N-N))
}

您可以在线尝试


2

Pyth,13个字节

csnM*zz*lztlz

@feersum解决方案的字面翻译。


2

CJam,25个字节

l$_e`0f=_:(.*:+\,_(*d/1\-

在线尝试

可以直接在问题中直接执行公式。

说明:

l     Get input.
$     Sort it.
_     Copy for evaluation of denominator towards the end.
e`    Run-length encoding of string.
0f=   Map letter/length pairs from RLE to only length.
      We now have a list of letter counts.
_     Copy list.
:(    Map with decrement operator. Copy now contains letter counts minus 1.
.*    Vectorized multiply. Results in list of n*(n-1) for each letter.
:+    Sum vector. This is the numerator.
\     Bring copy of input string to top.
,     Calculate length.
_(    Copy and decrement.
*     Multiply. This is the denominator, n*(n-1) for the entire string.
d     Convert to double, otherwise we would get integer division.
/     Divide.
1\-   Calculate one minus result of division to get final result.

1

J,37个字节

(1-([:+/]*<:)%+/*[:<:+/)([:+/"1~.=/])

但我相信它仍然可以缩短。

(1-([:+/]*<:)%+/*[:<:+/)([:+/"1~.=/]) 'AAABBC'

这只是以下功能的默认版本:

   fun =: 3 : 0
a1=.+/"1 (~.y)=/y
N=.(+/a1)*(<:+/a1)
n=.a1*a1-1
1-(+/n)%N
)

经过一些额外的打高尔夫球并使其正常工作后:(1-(%&([:+/]*<:)+/)@(+/"1@=))提供29个字节。27,如果我们不计算函数的花括号(1-(%&([:+/]*<:)+/)@(+/"1@=)),这很常见。注意:=y准确地来说(~.=/])y,组合变数(x u&v y= (v x) u (v y))也非常有用。
randomra

感谢您的建议!我仍在学习自己写默契表达。现在,我使用13:0逐步生成默认定义并合并。
gar 2015年

1

C,89

分数仅用于功能f,不包括不必要的空格,仅为了清楚起见,将其包括在内。该main功能仅用于测试。

i,c,n;
float f(char*v){
  n=strlen(v);
  for(i=n*n;i--;)c+=v[i%n]!=v[i/n]; 
  return 1.0*c/(n*n-n);
}

main(int C,char**V){
  printf("%f",f(V[1]));
}

它只是将每个字符与其他每个字符进行比较,然后除以比较总数。


1

Python 3、56

lambda s:sum(a!=b for a in s for b in s)/len(s)/~-len(s)

计算不相等元素的对,然后除以此类对的数量。


1

Haskell,83个字节

我知道我迟到了,发现了这个,忘了发帖了。Kinda对Haskell的要求不高,要求我将整数转换为可以彼此除的数。

s z=(l(filter id p)-l z)/(l p-l z) where p=[c==d|c<-z,d<-z]
l=fromIntegral.length

0

CJam,23个字节

1r$e`{0=,~}%_:+\,,:+d/-

从字节角度来看,这是对@RetoKoradi的答案的很小的改进,但是它使用了一个巧妙的技巧:

n个非负整数的总和等于n(n-1)/ 2,我们可以用它来计算问题公式中分数的分子和分母(均除以2)

CJam解释器中在线尝试。

怎么运行的

 r$                     e# Read a token from STDIN and sort it.
   e`                   e# Perform run-length encoding.
     {    }%            e# For each [length character] pair:
      0=                e#   Retrieve the length of the run (L).
        ,~              e#   Push 0 1 2 ... L-1.
                        e# Collect all results in an array.
            _:+         e# Push the sum of the entries of a copy.
               \,       e# Push the length of the array (L).
                 ,:+    e# Push 0 + 1 + 2 + ... + L-1 = L(L-1)/2.
                    d/  e# Cast to Double and divide.
1                     - e# Subtract the result from 1.

0

APL,26个字节

{1-+/÷/{⍵×⍵-1}({⍴⍵}⌸⍵),≢⍵}

说明:

  • ≢⍵:获取的第一维的长度。给定应该是字符串,则意味着字符串的长度。
  • {⍴⍵}⌸⍵:对于中的每个唯一元素,获取出现列表每个维度的长度。以1×≢⍵矩阵的形式给出了每个项目出现一次的次数。
  • ,:沿水平轴将两者串联。由于≢⍵是一个标量,另一个值是一列,我们得到一个2×≢⍵矩阵,其中第一列具有每个项目出现一个项目的次数,第二列具有项目总数。
  • {⍵×⍵-1}:对于矩阵中的每个单元格,计算N(N-1)
  • ÷/:按分区减少行数。这将每个项目的值除以总计的值。
  • +/:对每一行的结果求和。
  • 1-:从1中减去
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.