सभी पक्षों को देखने के लिए रोल!


10

मान लीजिए कि आपके पास 20-पक्षीय मरना है। आप उस मर को रोल करना शुरू करते हैं और इसे अंत में सभी 20 मूल्यों को रोल करने से पहले कुछ दर्जन बार रोल करना पड़ता है। आपको आश्चर्य है, मुझे सभी 20 मूल्यों को देखने का 50% मौका मिलने से पहले कितने रोल चाहिए? और nसभी nपक्षों को रोल करने से पहले मुझे मरने वाले रोल के कितने रोल चाहिए ?

कुछ शोध के बाद, आपको पता चलता है कि रोल के बाद सभी मानों को रोल करने की संभावना की गणना के लिए एक सूत्र मौजूद है ।nr

P(r, n) = n! * S(r, n) / n**r

जहाँ दूसरी तरह की स्टर्लिंग संख्याओं कोS(a, b) निरूपित किया जाता है , n वस्तुओं के एक सेट (प्रत्येक रोल) को गैर-रिक्त उपसमूह (प्रत्येक पक्ष) में विभाजित करने के तरीकों की संख्या।

आपको OEIS अनुक्रम भी मिलता है , जिसे हम कॉल करेंगे, जो R(n)कि सबसे छोटे से मेल खाता है rजहां P(r, n)कम से कम 50% है। nइस क्रम के वें कार्यकाल की गणना जितनी जल्दी हो सके, चुनौती है ।

चुनौती

  • एक को देखते हुए n, उस छोटी को खोजें r जहां 50% P(r, n)से अधिक या उससे अधिक है 0.5
  • आपके कोड को सैद्धांतिक nरूप से इनपुट के रूप में किसी भी गैर-नकारात्मक पूर्णांक को संभालना चाहिए , लेकिन हम केवल आपके कोड का परीक्षण रेंज में करेंगे 1 <= n <= 1000000
  • स्कोरिंग के लिए, हम हो जाएगा कुल समय चलाने के लिए आवश्यक ले R(n)इनपुट पर 1के माध्यम से 10000
  • हम यह जांचेंगे कि क्या आपके समाधान R(n)आपके आउटपुट पर हमारे संस्करण को चलाने के लिए सही हैं या नहीं , P(your_output, n) >= 0.5और यह देखने के लिए P(your_output - 1, n) < 0.5कि आपका आउटपुट वास्तव में rकिसी के लिए सबसे छोटा है n
  • आप S(a, b)अपने समाधान के लिए किसी भी परिभाषा का उपयोग कर सकते हैं। विकिपीडिया की कई परिभाषाएँ हैं जो यहाँ सहायक हो सकती हैं।
  • आप अपने समाधानों में बिल्ट-इन का उपयोग कर सकते हैं, जिसमें गणना S(a, b)करने वाले या P(r, n)सीधे गणना करने वाले लोग भी शामिल हैं।
  • आप 1000 मान तक R(n)और एक लाख स्टर्लिंग संख्या तक हार्डकोड कर सकते हैं , हालांकि इनमें से कोई भी हार्ड सीमा नहीं है, और यदि आप उन्हें बढ़ाने या कम करने के लिए एक ठोस तर्क दे सकते हैं, तो उन्हें बदला जा सकता है।
  • आप हर संभव जांच करने की जरूरत नहीं है rके बीच nऔर rहम के लिए देख रहे हैं, लेकिन आप छोटी से छोटी खोजने के लिए की जरूरत करना rऔर बस किसी भी नहीं rहै, जहां P(r, n) >= 0.5
  • आपके प्रोग्राम को ऐसी भाषा का उपयोग करना चाहिए जो विंडोज 10 पर स्वतंत्र रूप से चलाने योग्य हो।

कंप्यूटर के विनिर्देश जो आपके समाधान का परीक्षण करेंगे i7 4790k, 8 GB RAM। परीक्षण के लिए अपना कंप्यूटर उपलब्ध कराने के लिए @DJMcMayhem का धन्यवाद । संदर्भ के लिए अपने स्वयं के अनौपचारिक समय को जोड़ने के लिए स्वतंत्र महसूस करें , लेकिन डीजे का परीक्षण करने के बाद आधिकारिक समय प्रदान किया जाएगा।

परीक्षण के मामलों

n       R(n)
1       1
2       2
3       5
4       7
5       10
6       13
20      67       # our 20-sided die
52      225      # how many cards from a huge uniformly random pile until we get a full deck
100     497
366     2294     # number of people for to get 366 distinct birthdays
1000    7274
2000    15934
5000    44418
10000   95768
100000  1187943
1000000 14182022

यदि आपके कोई प्रश्न या सुझाव हैं तो मुझे बताएं। सौभाग्य और अच्छा अनुकूलन!


1
@JonathanAllan जानता था कि मुझे एक अलग शब्द चुनना चाहिए था। सर उठाने के लिए धन्यवाद।
शर्लक

जवाबों:


7

पायथन + न्यूमपी, 3.95 सेकंड्स

from __future__ import division
import numpy as np

def rolls(n):
    if n == 1:
        return 1
    r = n * (np.log(n) - np.log(np.log(2)))
    x = np.log1p(np.arange(n) / -n)
    cx = x.cumsum()
    y = cx[:-1] + cx[-2::-1] - cx[-1]
    while True:
        r0 = np.round(r)
        z = np.exp(y + r0 * x[1:])
        z[::2] *= -1
        r = r0 - (z.sum() + 0.5) / z.dot(x[1:])
        if abs(r - r0) < 0.75:
            return np.ceil(r).astype(int)

for n in [1, 2, 3, 4, 5, 6, 20, 52, 100, 366, 1000, 2000, 5000, 10000, 100000, 1000000]:
    print('R({}) = {}'.format(n, rolls(n)))

import timeit
print('Benchmark: {:.2f}s'.format(timeit.timeit(lambda: sum(map(rolls, range(1, 10001))), number=1)))

इसे ऑनलाइन आज़माएं!

यह काम किस प्रकार करता है

यह पी ( आर , एन ) के लिए बंद फॉर्म सीरीज़ का उपयोग करता है , और आर के संबंध में इसकी व्युत्पत्ति , संख्यात्मक स्थिरता और वैश्वीकरण के लिए पुन: व्यवस्थित, न्यूटन की विधि आर जैसे कि पी ( आर , एन ) के लिए खोज करने के लिए : राउंडिंग आर हर कदम से पहले एक पूर्णांक के लिए, जब तक कदम चाल r कम से कम 3/4 से। एक अच्छा प्रारंभिक अनुमान के साथ, यह आमतौर पर सिर्फ एक या दो पुनरावृत्तियों को लेता है।

x i = log (1 - i / n ) = log (( n - i ) / n )
cx i = log ( n ! / ( n - i - 1)! ⋅ n i + 1 )
y i = cx i + cx n - i - 2 - cx n - 1 = log binom ( n , i + 1)
z i = (-1) i + 1 om binom ( n) ,i + 1) + (( n - i - 1) / n ) r
1 + ) z i = n! ⋅ एस ( आर , एन ) / n आर = पी ( आर , एन )
z मैंएक्स मैं + 1 = (-1) मैं + 1 ⋅ binom ( n , मैं + 1) ⋅ (( एन - मैं - 1) / n ) आर लॉग (( एन - आई - 1) / एन)
Σ z मैंएक्स मैं + 1 = घ / डी आर पी ( आर , एन )


1
पूरे उत्तर पर उत्कृष्ट काम! सबसे पहले, मैंने महसूस किया जाना चाहिए था कि 0.366512था logकुछ उम्र के पहले। -log(log(2)मेरे अगले पुनरावृत्ति में उपयोग करेगा । दूसरा, न्यूटन की विधि का उपयोग करने का विचार भी बहुत चालाक है और मुझे यह देखकर खुशी हुई कि यह इतनी अच्छी तरह से काम करता है। तीसरा, मैं लगभग निश्चित रूप से चोरी करने जा रहा हूं exp(log(binom(n, i+1)) + r * log((n-i-1)/n)): पी कुडोस एक महान जवाब पर! : डी
शर्लक

1
मैंने आधिकारिक समय जोड़ा है! अच्छा जवाब BTW :)
जेम्स

2
मैं वास्तव में उलझन में हूँ। मैंने numpyआयात को बदल दिया from numpy import *और किसी कारण से समय मूल रूप से 0 पर आ गया ... इसे ऑनलाइन आज़माएं ?
नॉटजैगन

@ नोटजैन कैश हिट हो सकता है?
NoOneIsHere

1
मैं कई चीजों के लिए माफी माँगना चाहता हूँ: 1) जब मैंने सुधारों को खोजने की कोशिश की, तो आपके उत्तर की मेरी साहित्यिक चोरी; 2) इसका ठीक से पालन न करना और सिर्फ मेरा उत्तर ठीक करने की कोशिश करना; 3) कि यह माफी इतनी लंबी चली है। मैं इतना गिर गया कि पहले तो मैंने इस चुनौती को छोड़ दिया। पुनर्मूल्यांकन के एक छोटे से प्रयास में, मैंने आपको यह बताना उचित समझा कि इस उत्तर पर मेरा मुख्य सुधार न्यूटन की विधि से वेतन वृद्धि rके रूप में बदल रहा था , क्योंकि आपका प्रारंभिक सन्निकटन पहले से ही काफी अच्छा है। पीपीसीजी में आपको एक बार फिर देखने की उम्मीद है, और हर चीज के लिए खेद है।
शर्लक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.