โอกาสที่ฉันจะชนะรางวัลประตูคืออะไร?


12

บท ACM ท้องถิ่นของฉันมอบรางวัลให้กับคนที่เข้าร่วมการประชุม คุณจะได้รับโอกาสเพิ่มขึ้นในการชนะถ้าคุณไขปริศนาการเขียนโปรแกรม (แต่ฉันจะแก้ปริศนานั้นเสมอ) ดังนั้นบางคนมี 1 รายการขณะที่คนอื่นมี 2 แต่เดี๋ยวก่อน! วิธีการทำงานของโปรแกรมล็อตเตอรี่ไม่ใช่การเพิ่มในรายการอื่นเมื่อมีคนไขปริศนา แต่จะติดตามจำนวน "ชีวิต" ของบุคคลที่มีลดลงว่าหากบุคคลนั้นถูกเลือกในแต่ละรอบของอัลกอริทึมการสุ่มตัวอย่าง ดังนั้นจึงใช้งานได้เช่นนี้:

Doorknob: 1.  xnor: 2.  Justin: 2.  Alex: 1.  Dennis: 2.

จากนั้นโปรแกรมจะสุ่มเลือกหนึ่งใน[Doorknob, xnor, Justin, Alex, Dennis]นั้นลดจำนวนลง (พูดว่าเลือกJustin):

Doorknob: 1.  xnor: 2.  Justin: 1.  Alex: 1. Dennis: 2.

และทำซ้ำ หากจำนวน "ชีวิต" ของใครบางคนไปที่0(เลือกJustinอีกครั้ง) พวกเขาจะถูกลบออกจากรายการ:

Doorknob: 1.  xnor: 2.  Alex: 1.  Dennis: 2.

สิ่งนี้จะดำเนินต่อไปจนกว่าจะมีคนเหลืออีกคนหนึ่ง บุคคลนั้นเป็นผู้ชนะ

ตอนนี้คำถามจริงคือความน่าจะเป็นที่ฉันจะได้รับคืออะไร?


คุณจะได้รับสองอินพุต:

  • n. นี่คือจำนวนคนที่เข้าสู่การท้าทาย
  • k. นี่คือจำนวนของคนnที่มี 2 ชีวิต หมายเลขนี้รวมถึงคุณเสมอ

ดังนั้นถ้าฉันมีฟังก์ชั่นpและเรียกp(10, 5)ว่าน่าจะเป็นความน่าจะเป็นที่ได้รับรางวัลซึ่งมีทั้งหมด 10 คนซึ่ง 5 ในนั้นมีเพียง 1 ชีวิตในขณะที่ 5 (รวมถึงคุณ) มี 2 ชีวิต


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

วิธีการแก้ปัญหาของคุณอาจจะเป็นทางออกที่สุ่มซึ่ง outputs คำตอบ 4 THทศนิยมตำแหน่งที่มีความน่าจะเป็นสูง คุณอาจสันนิษฐานว่า RNG ในตัวที่คุณใช้นั้นสุ่มมาอย่างแท้จริงและต้องส่งคำตอบที่ถูกต้องโดยมีความน่าจะเป็นอย่างน้อย 90%

นอกจากนี้รหัสของคุณต้องการเพียงแค่การทำงานn, k <= 1000ถึงแม้ว่าฉันจะให้การทดสอบที่ใหญ่กว่านั้นสำหรับผู้ที่อยากรู้อยากเห็น


กรณีทดสอบ

หมายเหตุ: บางส่วนเป็นสูตรทั่วไป

n,    k   |  output
----------+---------
1,    1   |  1
2,    2   |  0.5
2,    1   |  0.75
3,    1   |  11/18 = 0.611111111
1000, 1   |  0.007485470860550352
4,    3   |  0.3052662037037037
k,    k   |  1/k
n,    1   |  (EulerGamma + PolyGamma[1 + n])/n    (* Mathematica code *)
          |  (γ + ψ(1 + n))/n
10,   6   |  0.14424629234373537
300,  100 |  0.007871966408910648
500,  200 |  0.004218184180294532
1000, 500 |  0.0018008560286627948
---------------------------------- Extra (not needed to be a valid answer)
5000, 601 |  0.0009518052922680399
5000, 901 |  0.0007632938197806958

สำหรับการตรวจสอบอีกสองสามข้อให้ทำp(n, 1) * nดังนี้:

n     |  output
------+---------
1     | 1
2     | 1.5 
3     | 1.8333333333333335
10    | 2.928968253968254
100   | 5.1873775176396215
-------------------------- Extra (not needed to be a valid answer)
100000| 12.090146129863305

ฉันไม่คุ้นเคยกับแท็กในไซต์นี้อีกต่อไป หากคุณคิดว่าแท็กที่เหมาะสมกว่านี้โปรดแก้ไข!
จัสติน

คำถามที่เกี่ยวข้องอย่างใกล้ชิดเกี่ยวกับ math.se: math.stackexchange.com/q/1669715/72616
Justin

ดังนั้น P (n, k) = ((k-1) / n) P (n, k-1) + ((nk) / n) P (n-1, k) + (1 / n) Q ( n, k-1) โดยที่ Q (n, k) = ((nk-1) / n) Q (n-1, k) + (k / n) Q (n, k-1) และ Q (1 , 0) = 1 ...
Leun Nun

@ KennyLau ฉันจะไม่พยายามตีความมัน แต่ระวังลิงค์ math.se เพราะมันใช้นิยามฟังก์ชั่นที่แตกต่างออกไปเล็กน้อย (ฉันเชื่อว่าkมันถูกปิดโดยคน ๆ หนึ่ง)
Justin

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

คำตอบ:


2

MATL , 42 ไบต์

:<~QXJx`J`tf1Zry0*1b(-tzq]f1=vts3e8<]6L)Ym

วิธีนี้ใช้แนวทางความน่าจะเป็น (Monte Carlo) การทดสอบดำเนินการเป็นจำนวนมากครั้งซึ่งมีความน่าจะเป็นประมาณ จำนวนของการรับรู้ถูกเลือกเพื่อให้แน่ใจว่าผลลัพธ์นั้นถูกต้องจนถึงทศนิยมที่สี่โดยมีความน่าจะเป็นอย่างน้อย 90% อย่างไรก็ตามมันใช้เวลานานมากและมีหน่วยความจำมากมาย ในลิงค์ด้านล่างจำนวนการรับรู้ลดลงด้วยปัจจัย 10 6เพื่อให้โปรแกรมสิ้นสุดในเวลาอันสมควร และเฉพาะทศนิยมแรกเท่านั้นที่รับประกันความถูกต้องพร้อมความน่าจะเป็นอย่างน้อย 90%

แก้ไข (29 กรกฎาคม 2016): เนื่องจากการเปลี่ยนแปลงของภาษาความต้องการจะถูกแทนที่ด้วย6L 3Lลิงค์ด้านล่างประกอบด้วยการดัดแปลงดังกล่าว

ลองออนไลน์!

พื้นหลัง

ให้pแทนความน่าจะเป็นที่จะคำนวณ การทดสอบที่อธิบายไว้ในความท้าทายจะทำงานเป็นจำนวนnครั้ง แต่ละครั้งไม่ว่าคุณจะชนะรางวัล (“ ความสำเร็จ ”) หรือไม่ก็ตาม ให้Nเป็นจำนวนความสำเร็จ ความน่าจะเป็นที่ต้องการสามารถประมาณจากNและn n ที่ใหญ่กว่าคือการประมาณที่แม่นยำยิ่งขึ้น คำถามที่สำคัญคือวิธีการเลือกnเพื่อตอบสนองความถูกต้องที่ต้องการคือเพื่อให้มั่นใจว่าอย่างน้อย 90% ของเวลาที่ผิดพลาดจะน้อยกว่า 10 -4

วิธีการ Monte Carlo สามารถ

  • ขนาดคงที่ : ค่าของnได้รับการแก้ไขล่วงหน้า (แล้วNเป็นแบบสุ่ม);
  • Variable-size : nถูกกำหนดโดยทันทีจากผลการจำลอง

ในบรรดาประเภทที่สองเป็นวิธีการที่ใช้ร่วมกันคือการแก้ไขN (หมายเลขที่ต้องการประสบความสำเร็จ) และให้การจำลองจนกว่าจำนวนของความสำเร็จที่จะประสบความสำเร็จ ดังนั้นnจึงเป็นแบบสุ่ม เทคนิคนี้เรียกว่าการสุ่มตัวอย่างแบบผกผันทวินามหรือการลบ - ทวินามมอนติคาร์โลมีข้อได้เปรียบที่ความแม่นยำของตัวประมาณค่าสามารถถูก จำกัด ขอบเขตได้ ด้วยเหตุผลนี้มันจะถูกใช้ที่นี่

โดยเฉพาะกับลบ - ทวินามมอนติคาร์โลx = ( N −1) / ( n − 1) เป็นตัวประมาณของp ; และความน่าจะเป็นที่xเบี่ยงเบนจากpมากกว่าอัตราส่วนที่กำหนดสามารถเป็นขอบเขตบน ตามสมการ (1) ในบทความนี้ (โปรดทราบว่าเงื่อนไข (2) เป็นที่พอใจ) การรับN = 2.75 · 10 8หรือใหญ่กว่าทำให้มั่นใจว่าp / xเป็นช่วงเวลา [1.0001, 0.9999] อย่างน้อย 90% ความน่าจะเป็น โดยเฉพาะนี่หมายความว่าxถูกต้องจนถึงตำแหน่งทศนิยมที่ 4 ที่มีความน่าจะเป็นอย่างน้อย 90% ตามที่ต้องการ

รหัสอธิบาย

รหัสใช้N = 3e8เพื่อบันทึกหนึ่งไบต์ โปรดทราบว่าการจำลองสถานการณ์จำนวนมากอาจใช้เวลานาน รหัสในลิงค์ใช้N = 300ซึ่งทำงานในระยะเวลาที่เหมาะสมมากขึ้น (น้อยกว่า 1 นาทีในคอมไพเลอร์ออนไลน์สำหรับกรณีทดสอบครั้งแรก); แต่นี่เป็นเพียงการยืนยันว่าทศนิยมแรกถูกต้องกับความน่าจะเป็นอย่างน้อย 90%

:        % Take k implicitly. Range [1 ... k]
<~       % Take n implicitly. Determine if each element in the previous array is
         % less than or equal than n
Q        % Add 1. This gives an array [2 ... 2 1 ... 1]
XJx      % Copy to clipboard J. Delete from stack
`        % Do...while. Each iteration is a Monte Carlo realization, until the 
         % desired nunber of successes is reached
  J      %   Push previously computed array [2 ... 2 1 ... 1]
  `      %   Do...while. Each iteration picks one door and decrements it, until
         %   there is only one
    t    %     Duplicate
    f    %     Indices of non-zero elements of array
    1Zr  %     Choose one of them randomly with uniform distribution
    y0*  %     Copy of array with all values set to 0
    1b(  %     Assign 1 to chosen index
    -    %     Subtract
    tzq  %     Duplicate. Number of nonzero elements minus 1. This is falsy if
         %     there was only one nonzero value; in this case the loop is exited
  ]      %   End do...while
  f1=    %   Index of chosen door. True if it was 1 (success), 0 otherwise
  v      %   Concatenate vertically to results from previous realizations
  ts3e8< %   Duplicate. Is the sum less than 3e8? If so, the loop is exited
]        % End do...while
6L)      % Remove last value (which is always 1)
Ym       % Compute mean. This gives (N-1)/(n-1). Implicitly display

ฮ่าฮ่าฉันไม่ได้ตระหนักว่า 90% จะทำให้มันยาก :-)
จัสติน

ใช่สี่ทศนิยมด้วยความเชื่อมั่น 90% เป็นความต้องการที่แข็งแกร่งจริงๆ :-)
หลุยส์ Mendo

2

Pyth, 34 ไบต์

Mc|!*HJ-GHch*J+*tHgGtH*gtGHKh-GHKG

ชุดทดสอบ

กำหนดฟังก์ชัน recursive ที่กำหนดค่าความจำgโดยใช้n , kเป็นอาร์กิวเมนต์ g 1000 500ส่งคืน0.0018008560286627952ภายในประมาณ 18 วินาที (ไม่รวมอยู่ในชุดทดสอบด้านบนเพราะหมดเวลาล่ามออนไลน์)

การแปล Python 3 โดยประมาณจะเป็น

@memoized
def g(n,k):
    return (not k*(n-k) or (1+(n-k)*((k-1)*g(n,k-1)+g(n-1,k)*(n-k+1)))/(n-k+1))/n

1

JavaScript (ES6), 65 ไบต์

f=(n,k,d=n-k)=>(!d||(f(n-1,k)*++d*--d+1+(--k&&f(n,k)*k*d))/++d)/n

อย่าลองด้วยจำนวนที่มาก แม้ f (30, 10) ต้องใช้เวลาพอสมควร

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