Kolmogorov ที่ไม่มีความซับซ้อน (-Smirnov)


12

ในสถิติบางครั้งมันมีประโยชน์ที่จะทราบว่าตัวอย่างข้อมูลสองตัวอย่างมาจากการแจกแจงต้นแบบเดียวกัน วิธีหนึ่งที่จะทำเช่นนี้คือการใช้สองตัวอย่างทดสอบ Kolmogorov-Smirnov

งานของคุณคือการเขียนโปรแกรมที่อ่านในอาร์เรย์จำนวนเต็มสองตัวที่ไม่ได้ลบและคำนวณค่าสถิติหลักที่ใช้ในการทดสอบ


รับอาร์เรย์Aและจำนวนจริงx, กำหนดฟังก์ชันการแจกแจงFโดย

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

รับสองอาร์เรย์A1และA2กำหนด

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

ทั้งสองตัวอย่าง Kolmogorov-Smirnov สถิติเป็นค่าสูงสุดของมากกว่าจริงทั้งหมดDx

ตัวอย่าง

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

แล้ว:

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

แคนซัส-สถิตสำหรับสองอาร์เรย์เป็นค่าสูงสุดของ1/2D

กรณีทดสอบ

[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

กฎระเบียบ

  • คุณสามารถเขียนฟังก์ชั่นหรือโปรแกรมเต็มรูปแบบ อินพุตอาจผ่าน STDIN หรืออาร์กิวเมนต์ของฟังก์ชันและเอาต์พุตอาจผ่าน STDOUT หรือส่งคืนค่า
  • คุณอาจสันนิษฐานว่ารายการหรือรูปแบบสตริงใด ๆ ที่ชัดเจนสำหรับอินพุตตราบใดที่มันสอดคล้องกันสำหรับทั้งสองอาร์เรย์
  • ในโอกาสที่ภาษาของคุณมีอยู่ภายในเครื่องคุณไม่สามารถใช้งานได้
  • คำตอบจะต้องมีความถูกต้องกับตัวเลขที่มีนัยสำคัญอย่างน้อย 3 ตัว
  • นี่คือดังนั้นโปรแกรมที่มีจำนวนไบต์น้อยที่สุดจะเป็นผู้ชนะ

อินพุตทั้งหมดจะเป็นอาร์เรย์จำนวนเต็มหรือสามารถมีคะแนนลอยได้หรือไม่
kennytm

@KennyTM เพียงจำนวนเต็มไม่ใช่ค่าลบ ฉันคิดว่าฉันคงเรื่องง่าย ๆ
Sp3000

มีค่าสูงสุดที่เราสามารถสันนิษฐานได้สำหรับอาร์เรย์? (เช่นรายการทั้งหมดของAอยู่ด้านล่างlength(A)?)
ข้อบกพร่อง

@flawr ไม่คุณไม่สามารถคาดเดาค่าสูงสุด
Sp3000

ฉันชอบชื่อ ฉันไม่พอใจการกำหนดเป้
edc65

คำตอบ:


10

APL ( 29 24)

(ขอบคุณ Zgarb สำหรับแรงบันดาลใจเพิ่มเติม)

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

นี่คือฟังก์ชันที่ใช้อาร์เรย์เป็นอาร์กิวเมนต์ซ้ายและขวา

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

คำอธิบาย:

{⌈/                                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
                          }

ฉันไม่รู้ว่าคุณสามารถทำได้⍺⍵! นั่นเป็นประโยชน์
Zgarb

1
นอกจากนี้ฉันคิดว่า⍳⌈/ไม่จำเป็นเนื่องจากได้รับค่าสูงสุดที่ค่าอาร์เรย์อย่างใดอย่างหนึ่ง
Zgarb

@Zgarb: ถูกต้องแน่นอนฉันแค่ต้องทดสอบค่าอาร์เรย์ที่เป็นไปได้ นั่นหมายความว่าฉันสามารถกำจัดได้0,เช่นกันเพราะมันจะทดสอบว่าถ้าอาร์เรย์มี ขอบคุณ! (และที่จะสอนให้ผมเป็นมักจะถ้าคุณมีที่จะเพิ่มในกรณีพิเศษที่หมายถึงขั้นตอนวิธีการที่ไม่เพียงพอที่เรียบง่าย.)
marinus

2
นี่คือคาถาที่แท้จริงที่นี่
Steven Lu

@ Sp3000: คุณเขียนอาร์เรย์หนึ่งองค์ประกอบอย่างถูกต้องหรือไม่? คุณไม่สามารถเขียน1ได้เพราะนั่นจะเป็นสเกลาร์ คุณควรเขียน(,1)แทน ถ้าคุณทำเช่นนั้นมันใช้งานได้
marinus

4

J - 39

ฉันแน่ใจว่าสามารถย่นระยะทางได้อีกมาก

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

การใช้

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

สิ่งนี้สร้างฟังก์ชั่นหรือใช้ stdin / stdout หรือไม่? ส่วนที่สองทำอะไรกันแน่ (ดูเหมือนจะใช้เวลานานในการเรียกใช้ฟังก์ชั่นใช่ไหม)
ข้อผิดพลาด

@flawr ฟังก์ชันคล้ายกับ APL
swish

ฉันคิดว่าคุณสามารถหลีกเลี่ยงการกำหนดอย่างชัดเจนfหากคุณใช้สิ่งที่ชอบ>./@:|@({.-{:)f"1@,แต่ฉันไม่แน่ใจ
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)

อินพุตเป็น 2 รายการของฟังก์ชัน g

ขอบคุณ: Sp3000, xnor, undergroundmonorail

บรรทัดที่ 2 สายแรกที่fอ่านเช่น "แฟกซ์" ฉันพบว่าน่าขบขันอย่างอ่อนโยน


2
sum(n>x for n in a)การนับจำนวนขององค์ประกอบของรายการที่ตอบสนองทรัพย์สินนั้นมันสั้นจะทำอย่างไร s=filterนอกจากนี้ก็ดูเหมือนว่าคุณไม่ได้ใช้ และสำหรับmaxคุณไม่จำเป็นต้องใช้วงเล็บในรายการ Python อนุญาตให้ฟังก์ชัน parens สองเท่าเป็น parens เข้าใจ
xnor

ขอบคุณ! ฉันใช้filterในรุ่นก่อนหน้าลืมที่จะลบมัน lenน่าเศร้าที่ฉันไม่สามารถลบคู่แรกของวงเล็บตั้งแต่นั้นมาก็จะเป็นเครื่องกำเนิดไฟฟ้าซึ่งไม่มี
Kroltan

คุณไม่ต้องการlenอ่านความคิดเห็นอีกครั้ง: P
undergroundmonorail

3

JavaScript (ES6) 99 119 128

การใช้งานจาวาสคริมากกว่าหรือน้อยกว่าตรงไปตรงมาอาจ golfable ในฟังก์ชั่น F ฉันใช้> แทน <= เป็น abs (F (a) -F (b)) === abs ((1-F (a)) - (1-F (b)))

ไม่มีคำจำกัดความของฟังก์ชั่นอีกต่อไปเป็นตัวกำหนดค่าเริ่มต้นในการแก้ไขครั้งล่าสุดนี้

อย่างที่ฉันพูดไปมันตรงไปตรงมา ฟังก์ชั่น F เป็นฟังก์ชั่น F ฟังก์ชั่น D เป็นฟังก์ชั่นที่ไม่มีชื่อที่ใช้ในบรรทัดที่ 2 มันถูกประเมินโดยใช้. map สำหรับแต่ละค่าที่มีอยู่ในสองอาร์เรย์เนื่องจากค่าสูงสุดสำหรับallreals จะต้องเป็นหนึ่งในนั้น ในที่สุดผู้ดำเนินการแพร่กระจาย (... ) จะใช้ในการผ่านอาร์เรย์ค่า D เป็นรายการพารามิเตอร์ไปยังฟังก์ชั่นสูงสุด

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))
))

ทดสอบในคอนโซล 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)))

เอาท์พุต

[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

ฉันอยากรู้เกี่ยวกับฟังก์ชั่นของคุณK: มันถูกต้องที่คุณกำหนดฟังก์ชั่นอื่น ๆF,Dในรายการอาร์กิวเมนต์? สิ่งนี้ทำตัวเหมือนมีข้อโต้แย้งที่เป็นทางเลือกหรือไม่?
ข้อบกพร่อง

@ flawr ใช่พวกเขาเป็นอาร์กิวเมนต์ตัวเลือกที่มีค่าเริ่มต้น ดังนั้นการหลีกเลี่ยงมลภาวะของพื้นที่แปรปรวนทั่วโลก (นั่นไม่ใช่ปัญหาในการเขียนโค้ดกอล์ฟ แต่อย่างไรก็ตาม ... )
edc65

1
นอกจากนี้เนื่องจากฟังก์ชันต้องการตัวแปร 2 ตัว (ดังนั้นวงเล็บ) จึงเป็น 2 ไบต์พิเศษเพื่อย้ายตัวแปรเหล่านั้นออกจากรายการตัวเลือก var ไปยังด้านในของร่างกายฟังก์ชัน
เครื่องมือเพิ่มประสิทธิภาพ


2

Matlab (121) (119)

นี่คือโปรแกรมที่ใช้สองรายการผ่าน stdin และพิมพ์ผลลัพธ์ไปยัง stdout มันเป็นสิ่งที่ยากและฉันพยายามจะเล่นกอล์ฟให้มากที่สุด K(a)ส่งกลับฟังก์ชั่นx -> F(a,x)ที่คำนวณ จากนั้นฟังก์ชั่นที่ไม่ระบุตัวตน@(x)abs(g(x)-h(x))ซึ่งสอดคล้องกับฟังก์ชั่นDจะถูกนำไปใช้กับจำนวนเต็มทุกค่าที่เป็นไปได้0:max([a,b])และผลลัพธ์สูงสุดจะปรากฏขึ้น ( arrayfunทำเหมือนกับmapภาษาอื่น: ใช้ฟังก์ชั่นกับทุกองค์ประกอบของอาเรย์)

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 ไบต์

โซลูชัน JavaScript ของ edc65ถูกย้ายไปยัง 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]).

ทดสอบ:

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]]]).

เอาท์พุท:

[[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

สถานะ 215

นี่คือ 90% ที่ได้รับอินพุตในรูปแบบที่สามารถใช้ได้เนื่องจาก STATA มีคำสั่ง 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)

โอ้ว้าวฉันไม่คิดว่าภาษาจะมี builtin สำหรับสิ่งนี้ ... ฉันเพิ่งจะทำการวิจัยและฉันคิดว่ามันจะเป็นการดีที่สุดที่จะไม่อนุญาตให้ buildins ต่อจากนี้ไป แต่คุณสามารถเก็บไว้ได้เพราะโพสต์ก่อนกฎ change :)
Sp3000

2

R, 65 ไบต์

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

ฟังก์ชันนี้ใช้สองเวกเตอร์เป็นอาร์กิวเมนต์และส่งกลับความแตกต่างสูงสุดของฟังก์ชันการแจกแจงสะสมเชิงประจักษ์

หากได้รับอนุญาตบิวด์อินมันจะลดลงเหลือเพียง 12 ไบต์:

ks.test(a,b)

1

Mathematica, 76 73 63

Mathematica มีฟังก์ชั่นในตัวKolmogorovSmirnovTestแต่ฉันจะไม่ใช้ที่นี่

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

การใช้งาน:

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

0.5


0

การติดตั้งอย่างรวดเร็วใน Python 3.4.2 (79 ไบต์):

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))

ตัวอย่าง:

>>> 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
สิ่งที่ต้องการคือการหาค่าสูงสุดของ D (x) สำหรับค่าจำนวนเต็มทั้งหมดของ x โปรดปฏิบัติตามข้อมูลจำเพาะของปัญหา
เครื่องมือเพิ่มประสิทธิภาพ

1
ยินดีต้อนรับ! ตามที่เครื่องมือเพิ่มประสิทธิภาพกล่าวว่าภารกิจคือการหาค่าสูงสุดDไม่ใช่เพื่อใช้Dเป็นฟังก์ชัน นอกจากนี้ฉันขอโทษถ้าฉันยังไม่ชัดเจน แต่คุณไม่สามารถสรุปได้A1และA2มีตัวแปรที่กำหนดไว้แล้ว (คุณสามารถใส่ไว้ในแลมบ์ดาได้เช่นlambda x,A1,A2:- ไม่เป็นไร)
Sp3000

นอกจากนี้ฉันได้เพิ่มการเน้นไวยากรณ์บางอย่าง - ฉันคิดว่ามันทำให้ดูดีขึ้น :)
Sp3000

ขออภัยเกี่ยวกับเรื่องนี้ฉันใหม่ที่นี่
Kapten

ไม่มีปัญหา :) หากมีอะไรไม่ชัดเจนคุณสามารถถามในความคิดเห็น แต่ยินดีต้อนรับอีกครั้ง!
Sp3000

0

Java - 633 622 ไบต์

ตกลงก่อนอื่นลองดีขึ้นที่ java ดังนั้นนั่นเป็นเหตุผลว่าทำไมฉันลองใน java ฉันรู้ว่าฉันจะไม่ทำดี แต่เอ๊ะมันสนุก อย่างที่สองฉันคิดอย่างสุจริตว่าฉันสามารถทำสิ่งนี้ได้ในทางที่น้อยลงจากนั้นฉันก็ขึ้นไปบนเวทีที่มีการเพิ่มเป็นสองเท่าทุกที่และการประกาศวิธีการนั้นหมายถึงการใช้วิธีการต่างๆ ในระยะสั้นฉันเป็นนักกอล์ฟที่ไม่ดี

แก้ไข: รูปแบบการใช้งาน> java K "2,10,10,10,1,6,7,2,10,4,7" "7,7,9,9,6,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;}}

คุณพูดถูก ปรับปรุง
ไบรอัน 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

(!) เป็นฟังก์ชัน kolmogorov-smirnov ซึ่งใช้สองรายการ


1
สนามกอล์ฟที่รวดเร็ว: ใช้งานmapมากกว่าfmap; ใช้maximumมากกว่าfoldr1 max; กำหนดl=fromIntegral.lengthและคุณสามารถกำจัดiและจากนั้นคุณสามารถร่นไป% l(filter(<=x)a)/l aทำให้มันลดลงเหลือ 84!
MtnViewMark

0

R, 107 ไบต์

แนวทางที่แตกต่าง

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}

Ungolfed

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
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.