심슨 다양성 지수


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 사이의 숫자입니다.

부동 소수점을 출력 할 때는 또는 같은 1또는 정확한 출력을 종료하지만 최소 4 자리를 표시하십시오 .1.00.375

다양성 지수 또는 엔트로피 측정 값을 구체적으로 계산하는 내장 기능을 사용할 수 없습니다. 테스트 사례에서 충분한 정확도를 얻는 한 실제 임의 샘플링이 좋습니다.

테스트 사례

AAABBC 0.73333
ACBABA 0.73333
WWW 0.0
CODE 1.0
PROGRAMMING 0.94545

리더 보드

다음은 Martin Büttner가 제공 한 언어 별 리더 보드 입니다.

답변이 표시되도록하려면 다음 마크 다운 템플릿을 사용하여 헤드 라인으로 답변을 시작하십시오.

# Language Name, N bytes

N제출물의 크기는 어디에 있습니까 ? 당신이 당신의 점수를 향상시킬 경우에, 당신은 할 수 있습니다 를 통해 눈에 띄는에 의해, 헤드 라인에 오래된 점수를 유지한다. 예를 들어 :

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


Gini-Simpson 지수를 사용하고 있습니다. 사용하기에 훨씬 더 좋은 방법은 유효 유형의 역수 인 Simpson 지수입니다.
Joe Z.

1
기본적으로 1/대신 1-. [아마추어 통계 rant 모자 끄기]
Joe Z.

답변:


5

파이썬 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

파이썬 3에서는 2 바이트가 짧을 것이므로 이미 알려주지 마십시오. :)


<>36 번 위치에서 앵글 브라켓은 무엇을하고 있습니까? 나는 그 구문을 본 적이 없다.
ApproachingDarknessFish

@TuttiFruttiJacuzzi :의 동의어입니다 !=.
RemcoGerlich

1
@TuttiFruttiJacuzzi 당신이 아니면 파이썬 2뿐입니다from __future__ import barry_as_FLUFL
matsjoyce

@ Vioz- l=len(s);거기에 없습니다
Sp3000

@ Sp3000 맞아, 몇 번이나 사용했는지 눈치 채지 못했습니다.
Kade

4

Pyth- 19 13 12 11 바이트

n에 대해 알려 주신 @isaacg에게 감사합니다

.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

@isaacg oh 자동으로 표시되는 것을 몰랐다.
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-(#/.~)+/@:%&(*<:)#)됩니다. 주변 괄호는 일반적으로 여기에서 계산되지 않기 1-(#/.~)+/@:%&(*<:)#때문에 (함수의 본문을 남겨두고 ) 20 바이트를 제공합니다.
randomra

4

파이썬 3, 66 58 바이트

이것은 질문에 제공된 간단한 계산 수식을 사용하고 있으며 너무 복잡하지 않습니다. 익명의 람다 함수이므로 사용하려면 이름을 지정해야합니다.

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}

이름이없는 모나드가 생성됩니다.

{
  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

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

파이썬 3, 56

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

같지 않은 요소의 쌍을 세고 그런 쌍의 수로 나눕니다.


1

하스켈, 83 바이트

늦어서 알았는데 게시를 잊어 버렸습니다. Haskell과 관련이없는 Kinda는 정수를 서로 나눌 수있는 숫자로 변환해야했습니다.

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에서 빼기
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.