Kolmogorov Bebas-Kompleksitas (-Smirnov)


12

Dalam statistik, terkadang berguna untuk mengetahui apakah dua sampel data berasal dari distribusi dasar yang sama. Salah satu cara untuk melakukan ini adalah dengan menggunakan uji Kolmogorov-Smirnov dua sampel .

Tugas Anda adalah menulis sebuah program yang membaca dalam dua array integer non-negatif yang tidak disortir dan menghitung statistik utama yang digunakan dalam pengujian.


Diberikan array Adan bilangan real x, tentukan fungsi distribusi Fdengan

F(A,x) = (#number of elements in A less than or equal to x)/(#number of elements in A)

Diberikan dua array A1dan A2, tentukan

D(x) = |F(A1, x) - F(A2, x)|

Statistik Kolmogorov-Smirnov dua sampel adalah nilai maksimum dari Dsemua nyata x.

Contoh

A1 = [1, 2, 1, 4, 3, 6]
A2 = [3, 4, 5, 4]

Kemudian:

D(1) = |2/6 - 0| = 1/3
D(2) = |3/6 - 0| = 1/2
D(3) = |4/6 - 1/4| = 5/12
D(4) = |5/6 - 3/4| = 1/12
D(5) = |5/6 - 4/4| = 1/6
D(6) = |6/6 - 4/4| = 0

Statistik KS untuk dua array adalah 1/2, nilai maksimum D.

Uji kasus

[0] [0] -> 0.0
[0] [1] -> 1.0
[1, 2, 3, 4, 5] [2, 3, 4, 5, 6] -> 0.2
[3, 3, 3, 3, 3] [5, 4, 3, 2, 1] -> 0.4
[1, 2, 1, 4, 3, 6] [3, 4, 5, 4] -> 0.5
[8, 9, 9, 5, 5, 0, 3] [4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9] -> 0.175824
[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7] [7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8] -> 0.363636

Aturan

  • Anda dapat menulis fungsi atau program lengkap. Input mungkin melalui STDIN atau argumen fungsi, dan output mungkin melalui STDOUT atau nilai balik.
  • Anda dapat mengasumsikan format daftar atau string yang tidak ambigu untuk input, asalkan konsisten untuk kedua array
  • Jika bahasa Anda memiliki builtin untuk ini, Anda tidak dapat menggunakannya.
  • Jawaban harus benar setidaknya untuk 3 angka penting
  • Ini adalah , sehingga program dalam byte paling sedikit menang

Apakah semua input akan menjadi array integer, atau dapatkah mereka mengandung floating point?
kennytm

@ KennyTM Hanya bilangan bulat non-negatif. Saya pikir saya akan menjaga hal-hal sederhana.
Sp3000

Apakah ada nilai maksimum yang dapat kita asumsikan untuk array? (Misalnya semua entri di Abawah length(A)?)
flawr

@ flawr Tidak, Anda tidak dapat mengasumsikan nilai maksimum
Sp3000

Saya suka judulnya. Saya stile menargetkan bagde kompleksitas kolmogorov, tapi tidak kali ini.
edc65

Jawaban:


10

APL ( 29 24)

(Terima kasih kepada Zgarb untuk inspirasi ekstra.)

{⌈/|-⌿⍺⍵∘.(+/≤÷(⍴⊣))∊⍺⍵}

Ini adalah fungsi yang mengambil array sebagai argumen kiri dan kanannya.

      8 9 9 5 5 0 3 {⌈/|-⌿⍺⍵∘.(+/≤÷(⍴⊣))∊⍺⍵} 4 9 0 5 5 0 4 6 9 10 4 0 9 
0.1758241758

Penjelasan:

{⌈/                                maximum of
   |                               the absolute value of
    -⌿                             the difference between
      ⍺⍵∘.(         )∊⍺⍵          for both arrays, and each element in both arrays
            +/≤                    the amount of items in that array ≤ the element
               ÷                   divided by
                (⍴⊣)              the length of that array
                          }

Saya tidak tahu Anda bisa melakukannya ⍺⍵! Itu berguna.
Zgarb

1
Juga, saya pikir ⍳⌈/tidak perlu, karena maksimum diperoleh tepat di salah satu nilai array.
Zgarb

@ Zgarb: Anda benar tentu saja, saya hanya perlu menguji untuk setiap nilai array yang mungkin. Itu berarti saya dapat menyingkirkannya 0,juga, karena akan menguji untuk itu jika array mengandungnya. Terima kasih! (Dan itu akan mengajari saya, seperti biasanya jika Anda harus menambahkan dalam kasus khusus, itu artinya algoritme tidak cukup sederhana.)
marinus

2
Ini sihir yang sebenarnya, di sini.
Steven Lu

@ Sp3000: apakah Anda menulis array satu elemen dengan benar? Anda tidak bisa hanya menulis 1, karena itu akan menjadi skalar. Anda harus menulis (,1). Jika Anda melakukannya, itu akan berhasil.
marinus

4

J - 39

Saya yakin bisa dipersingkat lebih banyak

f=:+/@|:@(>:/)%(]#)
>./@:|@((,f])-(,f[))

Pemakaian

2 10 10 10 1 6 7 2 10 4 7 >./@:|@((,f])-(,f[)) 7 7 9 9 6 6 5 2 7 2 8
0.363636

Apakah ini membuat fungsi atau menggunakan stdin / stdout? Apa sebenarnya yang dilakukan bagian kedua? (Terlihat agak lama untuk pemanggilan fungsi?)
flawr

@ flawr Fungsi, mirip dengan APL
swish

Saya pikir Anda bisa menghindari mendefinisikan secara eksplisit fjika Anda menggunakan sesuatu seperti >./@:|@({.-{:)f"1@,tapi saya tidak yakin.
FUZxxl

4

Python 3, 132 108 95 88

f=lambda a,x:sum(n>x for n in a)/len(a)
g=lambda a,b:max(abs(f(a,x)-f(b,x))for x in a+b)

Input adalah 2 daftar ke fungsi g

Terima kasih kepada: Sp3000, xnor, undergroundmonorail

Baris 2, panggilan pertama fberbunyi seperti "faks". Saya menemukan itu agak lucu


2
Untuk menghitung jumlah elemen daftar yang memenuhi properti, lebih pendek untuk dilakukan sum(n>x for n in a). Juga, sepertinya Anda tidak menggunakan s=filter. Dan untuk max, Anda sebenarnya tidak membutuhkan tanda kurung; Python memungkinkan fungsi parens berfungsi ganda sebagai parens pemahaman.
xnor

Terima kasih! Saya menggunakan filterdalam versi sebelumnya, lupa menghapusnya. Sayangnya saya tidak dapat menghapus pasangan pertama kurung sejak itu akan menjadi generator, yang tidak memiliki len.
Kroltan

Anda tidak perlu len, baca komentar lagi: P
undergroundmonorail

3

JavaScript (ES6) 99 119 128

Implementasi JavaScript lebih atau kurang langsung , mungkin lebih golf . Dalam fungsi F saya menggunakan> alih-alih <=, sebagai abs (F (a) -F (b)) === abs ((1-F (a)) - (1-F (b)))

Tidak ada lagi definisi fungsi sebagai parameter default dalam pengeditan terakhir ini.

Seperti yang saya katakan, itu mudah. Fungsi F adalah fungsi F, fungsi D adalah fungsi yang tidak disebutkan namanya yang digunakan pada baris 2. Dievaluasi menggunakan .map untuk setiap nilai yang ada di dua array, karena nilai maksimum untuk allreal harus menjadi salah satunya. Akhirnya, operator spread (...) digunakan untuk meneruskan larik nilai D sebagai daftar parameter ke fungsi maks.

K=(a,b)=>Math.max(...a.concat(b).map(x=>
  Math.abs((F=a=>a.filter(v=>v>x).length/a.length)(a)-F(b))
))

Uji di konsol FireFox / FireBug

;[[[0],[0]], [[0],[1]],
[[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]],
[[3, 3, 3, 3, 3],[5, 4, 3, 2, 1]],
[[1, 2, 1, 4, 3, 6],[3, 4, 5, 4]],
[[8, 9, 9, 5, 5, 0, 3],[4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9]],
[[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7],[7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8]]]
.forEach(x=>console.log(x[0],x[1],K(x[0],x[1]).toFixed(6)))

Keluaran

[0] [0] 0.000000
[0] [1] 1.000000
[1, 2, 3, 4, 5] [2, 3, 4, 5, 6] 0.200000
[3, 3, 3, 3, 3] [5, 4, 3, 2, 1] 0.400000
[1, 2, 1, 4, 3, 6] [3, 4, 5, 4] 0.500000
[8, 9, 9, 5, 5, 0, 3] [4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9] 0.175824
[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7] [7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8] 0.363636

Saya ingin tahu tentang fungsi Anda K: Apakah benar Anda mendefinisikan fungsi lain F,Ddalam daftar argumen? Apakah ini berperilaku seperti beberapa argumen opsional atau lebih?
flawr

@ flawr ya, itu adalah argumen opsional dengan nilai default. Jadi, hindari polusi ruang variabel global (itu bukan masalah dalam kode golf, tapi toh ...)
edc65

1
Plus, karena fungsi sudah membutuhkan 2 variabel (dengan demikian tanda kurung), itu akan menjadi 2 byte tambahan untuk memindahkan variabel-variabel tersebut keluar dari daftar var opsi ke dalam tubuh fungsi.
Pengoptimal

2

CJam, 33 31 byte

q~_:+f{\f{f<_:+\,d/}}z{~-z}%$W=

Input adalah array gaya CJam dari dua array.

Contoh:

[[8 9 9 5 5 0 3] [4 9 0 5 5 0 4 6 9 10 4 0 9]]

Keluaran:

0.17582417582417587

Cobalah online di sini


2

Matlab (121) (119)

Ini adalah program yang mengambil dua daftar melalui stdin dan mencetak hasilnya ke stdout. Ini adalah pendekatan strightfwd dan saya mencoba golf sebanyak mungkin. K(a)mengembalikan fungsi yang menghitung x -> F(a,x). Kemudian fungsi anonim @(x)abs(g(x)-h(x))yang sesuai dengan fungsi Dditerapkan ke setiap kemungkinan integer 0:max([a,b])dan hasil maksimal ditampilkan. ( arrayfunmelakukan hal yang sama seperti mapdalam bahasa lain: itu berlaku fungsi untuk setiap elemen array)

a=input('');b=input('');
K=@(a)@(x)sum(a<=x)/numel(a);
g=K(a);h=K(b);
disp(max(arrayfun(@(x)abs(g(x)-h(x)),0:max([a,b]))))

2

Erlang, 96 Bytes

Solusi JavaScript edc65 di porting ke Erlang.

f(A,B)->F=fun(A,X)->length([V||V<-A,V>X])/length(A)end,lists:max([abs(F(A,X)-F(B,X))||X<-A++B]).

Uji:

lists:foreach(fun ([H,T] = L) -> io:format("~p ~p~n", [L, w:f(H, T)]) end, [[[0],[0]], [[0],[1]],
        [[1, 2, 3, 4, 5],[2, 3, 4, 5, 6]],
        [[3, 3, 3, 3, 3],[5, 4, 3, 2, 1]],
        [[1, 2, 1, 4, 3, 6],[3, 4, 5, 4]],
        [[8, 9, 9, 5, 5, 0, 3],[4, 9, 0, 5, 5, 0, 4, 6, 9, 10, 4, 0, 9]],
        [[2, 10, 10, 10, 1, 6, 7, 2, 10, 4, 7],[7, 7, 9, 9, 6, 6, 5, 2, 7, 2, 8]]]).

Keluaran:

[[0],[0]] 0.0
[[0],[1]] 1.0
[[1,2,3,4,5],[2,3,4,5,6]] 0.20000000000000007
[[3,3,3,3,3],[5,4,3,2,1]] 0.4
[[1,2,1,4,3,6],[3,4,5,4]] 0.5
[[8,9,9,5,5,0,3],[4,9,0,5,5,0,4,6,9,10,4,0,9]] 0.17582417582417587
[[2,10,10,10,1,6,7,2,10,4,7],[7,7,9,9,6,6,5,2,7,2,8]] 0.36363636363636365

2

STATA 215

Ini adalah 90% memasukkan input ke dalam format yang dapat digunakan karena STATA sudah memiliki perintah ksmirnov.

di _r(a)
di _r(b)
file open q using "b.c",w
forv x=1/wordcount($a){
file w q "1,"(word($a,`x'))_n
}
forv x=1/wordcount($b){
file w q "2,"(word($b,`x'))_n
}
file close q
insheet using "b.c"
ksmirnov v2,by(v1)
di r(D)

Oh wow, saya tidak berpikir bahwa bahasa akan memiliki builtin untuk ini ... Saya baru saja melakukan riset dan saya memutuskan akan lebih baik untuk melarang builtin mulai sekarang, tetapi Anda dapat menyimpan ini karena sudah diposting sebelum aturan ubah :)
Sp3000

2

R, 65 byte

f=function(a,b){d=c(a,b);e=ecdf(a);g=ecdf(b);max(abs(e(d)-g(d)))}

Fungsi ini mengambil dua vektor sebagai argumen dan mengembalikan perbedaan maksimum fungsi distribusi kumulatif empirisnya.

Jika built-in diizinkan, itu akan berkurang menjadi hanya 12 byte:

ks.test(a,b)

1

Mathematica, 76 73 63

Mathematica memiliki fungsi bawaan KolmogorovSmirnovTest, tetapi saya tidak akan menggunakannya di sini.

k=N@MaxValue[Abs[#-#2]&@@(Tr@UnitStep[x-#]/Length@#&/@{##}),x]&

Pemakaian:

k[{1, 2, 1, 4, 3, 6}, {3, 4, 5, 4}]

0,5


0

Implementasi cepat dalam Python 3.4.2 (79 byte):

F=lambda A,x:len([n for n in A if n<=x])/len(A)
D=lambda x:abs(F(A1,x)-F(A2,x))

Contoh:

>>> A1 = [-5, 10, 8, -2, 9, 2, -3, -4, -4, 9]
>>> A2 = [-5, -3, -10, 8, -4, 1, -7, 6, 9, 5, -7]
>>> D(0)
0.045454545454545414

1
Syaratnya adalah untuk menemukan nilai maksimum D (x) untuk semua nilai integer x. Harap patuhi spesifikasi masalah.
Pengoptimal

1
Selamat datang! Seperti kata Pengoptimal, tugasnya adalah menemukan nilai maksimum D, bukan hanya mengimplementasikan Dsebagai fungsi. Juga, saya minta maaf jika saya tidak jelas, tetapi Anda tidak dapat mengasumsikan itu A1dan A2sudah variabel didefinisikan (Anda dapat menempatkan mereka di lambda, misalnya lambda x,A1,A2:- tidak apa-apa)
Sp3000

Saya juga telah menambahkan beberapa penyorotan sintaks - saya pikir itu membuatnya terlihat lebih cantik :)
Sp3000

Maaf tentang itu, saya baru di sini.
Kapten

Tidak ada masalah :) Jika ada yang tidak jelas, Anda dapat bertanya di komentar. Tapi sekali lagi, selamat datang!
Sp3000

0

Java - 633 622 Bytes

Ok, pertama, mencoba untuk menjadi lebih baik di java jadi itu sebabnya saya mencobanya di java, saya tahu saya tidak akan pernah melakukannya dengan baik, tapi eh, itu menyenangkan. kedua, saya benar-benar berpikir saya bisa melakukan ini dengan cara yang kurang, kemudian saya sampai pada tahap di mana ada dua kali lipat di mana-mana, dan deklarasi metode berarti menggunakan metode hanya menyelamatkan 4-5 karakter secara total. singkatnya, saya pegolf yang buruk.

sunting: format penggunaan> java K "2,10,10,10,1,6,7,2,10,4,7" "7,7,9,9,9,6,6,5,2,7,2 , 8 "

import java.lang.*;
class K{public static void main(String[]a){double[]s1=m(a[0]);double[]s2=m(a[1]);
int h=0;if(H(s1)<H(s2))h=(int)H(s2);else h=(int)H(s1);double[]D=new double[h];
for(int i=0;i<h;i++){D[i]=Math.abs(F(s1,i)-F(s2,i));}System.out.println(H(D));}
static double[]m(String S){String[]b=S.split(",");double[]i=new double[b.length];
for(int j=0;j<b.length;j++){i[j]=new Integer(b[j]);}return i;}
static double H(double[]i){double t=0;for(int j=0;j<i.length;j++)
{if(i[j]>t)t=i[j];}return t;}
static double F(double[]A,int x){double t=0;double l=A.length;
for(int i=0;i<l;i++){if(A[i]<=x)t++;}return t/l;}}

kamu benar. memperbarui.
Bryan Devaney

0

Haskell 96 83

l=fromIntegral.length
a%x=l(filter(<=x)a)/l a
a!b=maximum$map(\x->abs$a%x-b%x)$a++b

(!) adalah fungsi kolmogorov-smirnov yang mengambil dua daftar


1
beberapa golf cepat: gunakan mapdaripada fmap; gunakan maximumdaripada foldr1 max; mendefinisikan l=fromIntegral.lengthdan Anda dapat menyingkirkan i, dan kemudian Anda dapat mempersingkat %untuk l(filter(<=x)a)/l a. Turun ke 84!
MtnViewMark

0

R, 107 byte

Pendekatan yang berbeda

f=function(a,b){e=0
d=sort(unique(c(a,b)))
for(i in d-min(diff(d))*0.8)e=max(abs(mean(a<i)-mean(b<i)),e)
e}

Tidak disatukan

f=function(a,b){
    e=0
    d=sort(unique(c(a,b)))
    d=d-min(diff(d))*0.8
    for(i in d) {
        f=mean(a<i)-mean(b<i)
        e=max(e,abs(f))
    }
    e
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.