(ค่อนข้าง) เกิดวันเกิดความขัดแย้ง


20

พื้นหลัง

ขัดแย้งวันเกิดเป็นปัญหาที่เป็นที่นิยมในทฤษฎีความน่าจะได้อย่างหวุดหวิดซึ่งสัญชาตญาณทางคณิตศาสตร์ (คนส่วนใหญ่) คำแถลงปัญหาคือ:

เมื่อพิจารณาจากคนNคนความน่าจะเป็นที่อย่างน้อยสองคนมีวันคล้ายวันเกิด (ไม่คำนึงถึงปี)

ปัญหานี้มักจะทำให้ง่ายขึ้นโดยไม่สนใจวันก้าวกระโดดอย่างสิ้นเชิง ในกรณีนี้คำตอบสำหรับN = 23คือP (23) ≈ 0.5072972 (เป็นตัวอย่างทั่วไป) บทความ Wikipedia ที่เชื่อมโยงอธิบายถึงวิธีที่จะเกิดความน่าจะเป็นนี้ อีกวิธีหนึ่งวิดีโอ Numberphile นี้ทำได้ดีมาก

อย่างไรก็ตามสำหรับความท้าทายนี้เราต้องการทำถูกต้องและอย่าเพิกเฉยปีที่ผ่านมา มันซับซ้อนกว่านี้เล็กน้อยเนื่องจากตอนนี้วันที่ 29 กุมภาพันธ์จะต้องมีการเพิ่ม แต่วันเกิดโดยเฉพาะอย่างยิ่งนี้มีโอกาสน้อยกว่าคนอื่น ๆ ทั้งหมด

นอกจากนี้เราจะใช้กฎปีอธิกสุรทินแบบเต็ม:

  • ถ้าปีหารด้วย 400 มันจะเป็นปีอธิกสุรทิน
  • มิฉะนั้นถ้าปีหารด้วย 100 จะไม่ใช่ปีอธิกสุรทิน
  • มิฉะนั้นถ้าปีหารด้วย 4 จะเป็นปีอธิกสุรทิน
  • อย่างอื่นมันไม่ใช่ปีอธิกสุรทิน

สับสน? หมายความว่าปี 1700, 1800, 1900, 2100, 2200, 2300 ไม่ใช่ปีอธิกสุรทิน แต่ 1600, 2000, 2400 เป็น (เช่นเดียวกับปีอื่น ๆ หารด้วย 4) ปฏิทินนี้ทำซ้ำทุก 400 ปีและเราจะถือว่าการกระจายวันเกิดในช่วง 400 ปีที่ผ่านมาเป็นแบบเดียวกัน

ผลการแก้ไขสำหรับN = 23คือตอนนี้P (23) ≈ 0.5068761

ความท้าทาย

ให้เป็นจำนวนเต็ม1 ≤ N < 100กำหนดความน่าจะเป็นที่Nคนอย่างน้อยสองคนมีวันคล้ายวันเกิดภายใต้การพิจารณาของกฎปีอธิกสุรทิน ผลลัพธ์ควรเป็นเลขทศนิยมหรือจุดคงที่ซึ่งมีความแม่นยำถึงทศนิยมอย่างน้อย 6 ตำแหน่ง เป็นที่ยอมรับได้ที่จะตัดทอนศูนย์ต่อท้าย

คุณสามารถเขียนโปรแกรมหรือฟังก์ชั่น, รับอินพุตผ่าน STDIN (หรือทางเลือกที่ใกล้เคียงที่สุด), อาร์กิวเมนต์บรรทัดคำสั่งหรืออาร์กิวเมนต์ฟังก์ชันและส่งออกผลลัพธ์ผ่านทาง STDOUT (หรือทางเลือกที่ใกล้เคียงที่สุด), ค่าส่งคืนของฟังก์ชันหรือฟังก์ชัน

โซลูชันของคุณจะต้องสามารถสร้างเอาต์พุตสำหรับอินพุตทั้งหมด 99 รายการในเวลาไม่กี่วินาที นี่คือหลักในการแยกแยะวิธีการมอนติคาร์โลกับตัวอย่างจำนวนมากดังนั้นหากคุณใช้อัลกอริทึมที่รวดเร็วและแม่นยำในภาษาลึกลับที่ช้าเกินไปฉันยินดีที่จะให้กฎนี้แก่คุณ

กรณีทดสอบ

นี่คือตารางผลลัพธ์เต็มรูปแบบ:

 1 => 0.000000
 2 => 0.002737
 3 => 0.008195
 4 => 0.016337
 5 => 0.027104
 6 => 0.040416
 7 => 0.056171
 8 => 0.074251
 9 => 0.094518
10 => 0.116818
11 => 0.140987
12 => 0.166844
13 => 0.194203
14 => 0.222869
15 => 0.252642
16 => 0.283319
17 => 0.314698
18 => 0.346578
19 => 0.378764
20 => 0.411063
21 => 0.443296
22 => 0.475287
23 => 0.506876
24 => 0.537913
25 => 0.568260
26 => 0.597796
27 => 0.626412
28 => 0.654014
29 => 0.680524
30 => 0.705877
31 => 0.730022
32 => 0.752924
33 => 0.774560
34 => 0.794917
35 => 0.813998
36 => 0.831812
37 => 0.848381
38 => 0.863732
39 => 0.877901
40 => 0.890932
41 => 0.902870
42 => 0.913767
43 => 0.923678
44 => 0.932658
45 => 0.940766
46 => 0.948060
47 => 0.954598
48 => 0.960437
49 => 0.965634
50 => 0.970242
51 => 0.974313
52 => 0.977898
53 => 0.981043
54 => 0.983792
55 => 0.986187
56 => 0.988266
57 => 0.990064
58 => 0.991614
59 => 0.992945
60 => 0.994084
61 => 0.995055
62 => 0.995880
63 => 0.996579
64 => 0.997169
65 => 0.997665
66 => 0.998080
67 => 0.998427
68 => 0.998715
69 => 0.998954
70 => 0.999152
71 => 0.999314
72 => 0.999447
73 => 0.999556
74 => 0.999645
75 => 0.999717
76 => 0.999775
77 => 0.999822
78 => 0.999859
79 => 0.999889
80 => 0.999913
81 => 0.999932
82 => 0.999947
83 => 0.999959
84 => 0.999968
85 => 0.999976
86 => 0.999981
87 => 0.999986
88 => 0.999989
89 => 0.999992
90 => 0.999994
91 => 0.999995
92 => 0.999996
93 => 0.999997
94 => 0.999998
95 => 0.999999
96 => 0.999999
97 => 0.999999
98 => 0.999999
99 => 1.000000

(แน่นอนP (99)เพียง1.0เนื่องจากการปัดเศษความน่าจะเป็นจะไม่ถึง1.0จนกระทั่งP (367) )


7
1. หากคุณกำลังจะอวดตัวเองคุณควรคำนึงถึงว่าวันเกิดจะไม่กระจายอย่างสม่ำเสมอตลอดทั้งปี 2. ความเกี่ยวข้องที่แม่นยำของกฎปีอธิกสุรทินนั้นขึ้นอยู่กับว่ามีการตั้งสมมติฐานเกี่ยวกับอายุยืนของมนุษย์อย่างไร มีแนวคิดที่จะตัดจำหน่ายตลอดทั้งรอบ 400 ปีหรือไม่?
Peter Taylor

1
@PeterTaylor ใช่สมมติว่ามีการกระจายแบบครบวงจรตลอดทั้ง 400 ปี ฉันไม่เคยพูดชุดของคนN ที่ยังมีชีวิตอยู่ในเวลาเดียวกัน ;)
Martin Ender

คำตอบ:


6

Pyth, 31 34ไบต์

Jt.2425K366-1c.xX0rK-KQ*JQ^+KJQ

สาธิต , เทียมทดสอบ

สิ่งนี้ทำงานคล้ายกับเวอร์ชั่นเก่ายกเว้นว่าแทนที่จะสร้างค่า (366 + n * (.2425 - 1)) แยกจากกันและคูณมันบนมันเริ่มต้นด้วยการสร้างรายการที่ขยายจาก 366 ถึง 365 - n + 2 จากนั้นปรับเปลี่ยน 366 ให้เป็น (366 + n * (.2425 - 1)) จากนั้นนำผลิตภัณฑ์ของรายการ นอกจากนี้ยังใช้ค่าคงที่ 366 และ -.7575 แทน 365 และ. 2425


เวอร์ชั่นเก่า:

Pyth, 34 ไบต์

J.2425K365-1c*+hK*QtJ.xrK-hKQ^+KJQ

มีสองวิธีที่เป็นไปได้ที่จะไม่มีคู่คนที่มีวันเกิดเดียวกันคือ: ทุกคนมีวันเกิดที่แตกต่างกันและไม่มีใครมีวันคล้ายวันเกิดในวันที่ 29 กุมภาพันธ์และมีคนเกิดวันที่ 29 และคนอื่น ๆ วันเกิดในวันปกติ

ความน่าจะเป็นที่เกิดขึ้นครั้งแรกคือ (365 * 364 * ... 365 - n + 1) / (365.2425 ^ n)

ความน่าจะเป็นที่เกิดขึ้นครั้งที่สองคือ (365 * 364 * ... 365 - n + 2) * .2425 * n / (365.2425 ^ n)

สิ่งเหล่านี้สามารถเขียนร่วมกันเป็น (365 * 364 * ... 365 - n + 2) * (365 - n + 1 + .2425 * n) / (365.2425 ^ n) = (365 * 364 * ... 365 - n + 2) * (365 + 1 + (.2425 - 1) * n) / (365.2425 ^ n)

นี่คือความน่าจะเป็นที่ไม่มีคู่ดังนั้นความน่าจะเป็นอย่างน้อยหนึ่งคู่คือหนึ่งลบด้วยจำนวนที่สูงกว่า

J = .2425
K = 365
.xrK-hKQ = (365 * 364 * ... 365 - n + 2)
+hK*QtJ = (365 + 1 + n * (.2425 - 1))
^+KJQ = (365.2425 ^ n)

5

Python, 179 178 144 143 140 136 135 133

f=.2425
g=365+f
a=lambda n:(n and(365-n)*a(n-1)or 365)/g
b=lambda n:(n<2and f or(367-n)*b(n-1)+a(n-2)*f)/g
p=lambda n:1-a(n-1)-b(n)

p(n)ให้ผลลัพธ์ เปลี่ยน.2425เป็นfractions.Fraction(97,400)รับผลลัพธ์ที่แน่นอน


คุณไม่จำเป็นต้องช่องว่างระหว่างและ2 and
isaacg

คุณไม่สามารถใส่ใน1/สำหรับgและหารด้วยมันแทน?
xnor

@ xnor ใช่เลยเมื่อเวลาผ่านไปสิ่งเหล่านี้จะหายไป :) สิ่งที่ครั้งหนึ่งการเพิ่มประสิทธิภาพกลายเป็นสิ่งที่ไม่ดีในภายหลัง
orlp

คุณสามารถแนะนำe=365และแทนที่ 365 ด้วย e และ 367 โดย e + 2
Willem

@ วิลเล็มนั่นไม่สั้น
orlp

2

Python 155 153 151 142 140 ไบต์

d=146097
b=d/400
c=97/d
e=lambda n:n<2and 1-97/d or e(n-1)*(366-n)/b
f=lambda n:n<2and c or f(n-1)*(367-n)/b+e(n-1)*c
a=lambda n:1-e(n)-f(n)

โทร a(n)ผล เพื่อผลลัพธ์ที่แน่นอนห่อdเป็นเศษส่วน

ทดสอบที่นี่

ใช้เทคนิคเดียวกับที่นี่แต่ด้วยค่าคงที่ที่ปรับเปลี่ยน


คุณไม่จำเป็นต้องช่องว่างระหว่างและ2 and
isaacg

ฉันคิดว่ามันเป็น 98 (แม้ว่าฉันอาจจะบ้าเป็นความผิดพลาดในการคำนวณ ... )
ทิม

1

รหัสเครื่อง 80386 ขนาด 43 ไบต์

Hexdump ของรหัส:

68 75 6e 33 3b 68 5a eb 07 3b 8b c4 49 d9 e8 d9
e8 d8 00 d9 e8 d9 40 04 de ea d8 c9 d9 00 de eb
e2 f3 d8 ca d9 e8 d8 e1 58 58 c3

ฉันเริ่มจากสูตรต่อไปนี้ (สำหรับความน่าจะเป็นเสริม):

\ แยง \ limits_ {i = 0} ^ {k-2} (1- \ frac {97 + 400 * i} {d}) * (1- \ frac {303 * (k-1)} {d})

(นี่d = 366 * 400 - 303คือจำนวนวันใน 400 ปี)

นี่คือรหัส c ++ ที่ใช้งาน (มันได้รับการปรับปรุงเล็กน้อยแล้ว):

double it_opt(int k)
{
    double d = 366 * 400 - 303; // number of days in 400 years
    double result = 1; // probability of no coincidences
    const float const1 = float(400 / d);
    const float const2 = float(303 / d);
    double v1 = 1 + const2;
    double v2 = 1;

    for (int i = 0; i < k - 1; ++i)
    {
        v1 -= const1;
        result *= v1;
        v2 -= const2;
    }
    result *= v2;
    return 1 - result;
}

รหัสมีการจัดเรียงดังนั้นจึงต้องมีจำนวนค่าคงที่ขั้นต่ำ - เพียงสอง ( 400 / dและ303 / d) ฉันใช้floatประเภทเพื่อเป็นตัวแทนพวกเขาเพราะมันใช้พื้นที่น้อย (4 ไบต์ต่อค่าคงที่) นอกจากนี้ฉันไม่ต้องการคูณconst2ด้วยk - 1(เพราะต้องแปลงk - 1เป็นfloat); ลบรหัสconst2ซ้ำ ๆ แทน

นี่คือรายการภาษาแอสเซมบลี:

    ; // fastcall convention - parameter k is in ecx
    ; // result must be returned in st
    push dword ptr 0x3b336e75; // const1 = [esp + 4]
    push dword ptr 0x3b07eb5a; // const2 = [esp]
    mov eax, esp;              // use [eax] instead of [esp] - 1 byte less
    dec ecx;                   // calculate k - 1
    fld1;                      // initiaze result = 1
    fld1;                      // initialize v1
    fadd [eax];
    fld1;                      // initialilze v2
myloop:
    fld dword ptr [eax + 4];
    fsubp st(2), st;            // update v1
    fmul st, st(1);             // update result
    fld dword ptr [eax];
    fsubp st(3), st;            // update v2
    loop myloop;                // loop
    fmul st, st(2);             // update result by v2
    fld1;
    fsub st, st(1);             // complement result
    pop eax;                    // restore stack
    pop eax;                    // restore stack
    ret;                        // return
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.