बुलबुले की व्यवस्था करना


26

ध्यान दें, math.stackexchange पर पूछे गए प्रश्न से कॉपी की गई चुनौती ।

हाल ही में, मुझे बुलबुले उड़ाने में काफी कुछ हासिल हुआ। सबसे पहले मैं इस तरह बुलबुले उड़ाऊंगा: यहाँ छवि विवरण दर्ज करें

लेकिन फिर चीजें अजीब होने लगीं:

यहाँ छवि विवरण दर्ज करें

थोड़ी देर बाद, मैं कुछ बहुत अजीब बुलबुले उड़ा रहा था:

यहाँ छवि विवरण दर्ज करें

सैकड़ों उड़ाने के बाद, शायद हजारों ऐसे बुलबुले, मेरे माथे को अचानक इस सवाल के साथ झुर्री हुई है: एन बुलबुले को देखते हुए, आप उन्हें कितने अलग-अलग तरीकों से व्यवस्थित कर सकते हैं? उदाहरण के लिए यदि n = 1, केवल 1 व्यवस्था है। यदि n = 2, 2 व्यवस्थाएं हैं। यदि n = 3, 4 व्यवस्थाएँ हैं। यदि n = 4, 9 व्यवस्थाएं हैं।

यहां 4 बुलबुले की 9 व्यवस्थाएं दी गई हैं:
यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें यहाँ छवि विवरण दर्ज करें

इन अद्भुत बुलबुले को उड़ाने के बाद, मैंने फैसला किया कि मुझे उनके साथ अपनी व्यवस्थाओं को गिनने की खुशी साझा करनी चाहिए। तो यहाँ आपका काम है:


लक्ष्य

एक प्रोग्राम, फ़ंक्शन, या समान लिखें जो आपके द्वारा nबुलबुले की व्यवस्था करने के तरीकों की संख्या को गिनता है ।


इनपुट

nबुलबुले की संख्या। n> 0


उत्पादन

इन बुलबुले को व्यवस्थित करने के तरीकों की संख्या।


जीत का मानदंड

यह वास्तव में अच्छा होगा यदि हम आपके कोड के चारों ओर एक बुलबुला उड़ा सकते हैं। जितना छोटा आप अपना कोड बनाते हैं, उतना आसान होगा। तो जो व्यक्ति कम से कम बाइट्स के साथ कोड बनाता है वह प्रतियोगिता जीत जाएगा।


अतिरिक्त जानकारी

OEIS


5
यदि बुलबुले अंतर कर सकते हैं तो यह एक खुली समस्या है , n = 4 के लिए 173 समाधान
orlp

@orlp सौभाग्य से, इन बुलबुले को काटना नहीं है।
TheNumberOne

1
है 0एक मान्य इनपुट?
मार्टिन एंडर

@ केन-एन हां। नीचे पहले से ही OEIS लिंक मौजूद है
रोमन ग्रैफ

ऊप्स! बेवकूफ टिप्पणी समय हटाएं ...
केन वाईएन

जवाबों:


12

पायथन 2, 92 87 बाइट्स

a=lambda n:n<2or sum((k%d<1)*d*a(d)*a(n-k)for k in range(1,n)for d in range(1,1+k))/~-n

सादे अंग्रेजी में: गणना करने के लिए a(n)हम प्रत्येक सकारात्मक पूर्णांक के d*a(d)*a(n-k)प्रत्येक भाजक dके लिए गणना करते हैं जो इन सभी kसे छोटा या बराबर होता है n, और इनसे विभाजित होता है n-1

इसे तेज़ी से चलाने के लिए, पायथन 3 ( उपरोक्त फ़ंक्शन के /साथ बदलना //) में चलाएं और याद रखें:

import functools
a = functools.lru_cache(None)(a)

यदि आप ऐसा करते हैं तो यह a(50) = 425976989835141038353तुरंत गणना करता है।


वाह ये अच्छा है। मुझे लगता है कि lru_cache()समारोह को याद करता है?
पैट्रिक रॉबर्ट्स

@PatrickRoberts हां, आमतौर पर यह एक फ़ंक्शन डेकोरेटर के रूप में उपयोग किया जाता है, लेकिन आप इसे मैन्युअल रूप से एक फ़ंक्शन पर भी लागू कर सकते हैं।
orlp

@PatrickRoberts यहाँ के लिए डॉक्स हैंlru_cache
PM 2Ring

इस समारोह के लिए लौटता Trueहै n<2। मुझे लगता है कि इसके लिए ठीक है n=1, क्योंकि पायथन Trueसंख्यात्मक अंक में 1 का मूल्यांकन करता है, लेकिन a(0)0. वापस आ जाना चाहिए। आप इसे ठीक कर सकते हैं , लेकिन n<2 and n or sum...अधिक कॉम्पैक्ट तरीका हो सकता है।
PM 2Ring

मुझे लगता है कि एक तर्क दिया जा सकता है कि शून्य बुलबुले की व्यवस्था करने का एक तरीका है, लेकिन यह A000081 के अनुरूप नहीं है। OTOH, अगर हमें केवल सकारात्मक के लिए हल करने की आवश्यकता है, तो हम nइस कोने के मामले को सुरक्षित रूप से अनदेखा कर सकते हैं, क्योंकि यह उच्चतर के लिए पुनरावर्ती कॉल को प्रभावित नहीं करता है n
PM 2Ring

10

जीएनयू प्रोलॉग, 98 बाइट्स

b(x,0,x).
b(T/H,N,H):-N#=A+B+1,b(H,A,_),b(T,B,J),H@>=J.
c(X,Y):-findall(A,b(A,X,_),L),length(L,Y).

यह उत्तर इस बात का एक बड़ा उदाहरण है कि कैसे प्रोलॉग सबसे सरल I / O स्वरूपों के साथ संघर्ष कर सकता है। यह प्रॉब्लम को हल करने के लिए एल्गोरिदम के बजाय समस्या का वर्णन करके सही प्रोलॉग शैली में काम करता है: यह निर्दिष्ट करता है कि कानूनी बबल व्यवस्था के रूप में क्या मायने रखता है, प्रोलॉग को उन सभी बबल व्यवस्था को उत्पन्न करने के लिए कहता है, और फिर उन्हें गिनता है। पीढ़ी 55 वर्ण (कार्यक्रम की पहली दो पंक्तियाँ) लेती है। गिनती और I / O अन्य 43 (तीसरी पंक्ति, और दो भागों को अलग करने वाली नई पंक्ति) लेता है। मुझे यकीन है कि यह एक समस्या नहीं है कि ओपी ने I / O के साथ संघर्ष करने के लिए भाषाओं का कारण बनने की उम्मीद की है! (नोट: स्टैक एक्सचेंज का सिंटैक्स हाइलाइटिंग पढ़ने के लिए कठिन है, आसान नहीं है, इसलिए मैंने इसे बंद कर दिया)।

व्याख्या

आइए एक समान कार्यक्रम के छद्म संस्करण के साथ शुरू करें जो वास्तव में काम नहीं करता है:

b(Bubbles,Count) if map(b,Bubbles,BubbleCounts)
                and sum(BubbleCounts,InteriorCount)
                and Count is InteriorCount + 1
                and is_sorted(Bubbles).
c(Count,NPossibilities) if listof(Bubbles,b(Bubbles,Count),List)
                       and length(List,NPossibilities).

यह स्पष्ट रूप से स्पष्ट होना चाहिए कि कैसे bकाम करता है: हम छंटनी सूचियों के माध्यम से बुलबुले का प्रतिनिधित्व कर रहे हैं (जो मल्टीसेट का एक सरल कार्यान्वयन है जो समान मल्टीसीट को बराबर की तुलना करता है), और एक बुलबुले []में 1 की गिनती होती है, जिसमें एक बड़ा बुलबुला होता है। प्लस 1 के अंदर बुलबुले की कुल संख्या के बराबर 1. 4 की गिनती के लिए, यह कार्यक्रम होगा (यदि यह काम किया) निम्नलिखित सूचियां उत्पन्न करेगा:

[[],[],[],[]]
[[],[],[[]]]
[[],[[],[]]]
[[],[[[]]]]
[[[]],[[]]]
[[[],[],[]]]
[[[],[[]]]]
[[[[],[]]]]
[[[[[]]]]]

यह कार्यक्रम कई कारणों से एक उत्तर के रूप में अनुपयुक्त है, लेकिन सबसे अधिक दबाव यह है कि प्रोलॉग वास्तव में एक mapविधेय नहीं है (और यह लिखना बहुत अधिक बाइट्स ले जाएगा)। इसलिए इसके बजाय, हम प्रोग्राम को इस तरह लिखते हैं:

b([], 0).
b([Head|Tail],Count) if b(Head,HeadCount)
                    and b(Tail,TailCount)
                    and Count is HeadCount + TailCount + 1
                    and is_sorted([Head|Tail]).
c(Count,NPossibilities) if listof(Bubbles,b(Bubbles,Count),List)
                       and length(List,NPossibilities).

यहाँ दूसरी बड़ी समस्या यह है कि जब यह प्रोलॉग के मूल्यांकन के क्रम में काम करता है, तो यह एक अनंत लूप में चला जाता है। हालाँकि, हम प्रोग्राम को थोड़ा पीछे करके अनंत लूप को हल कर सकते हैं:

b([], 0).
b([Head|Tail],Count) if Count #= HeadCount + TailCount + 1
                    and b(Head,HeadCount)
                    and b(Tail,TailCount)
                    and is_sorted([Head|Tail]).
c(Count,NPossibilities) if listof(Bubbles,b(Bubbles,Count),List)
                       and length(List,NPossibilities).

यह काफी अजीब लग सकता है - हम एक साथ जोड़ रहे हैं इससे पहले कि हम जानते हैं कि वे क्या हैं - लेकिन जीएनयू #=प्रोलॉग नॉनकौसल अंकगणित के उस प्रकार से निपटने में सक्षम है, और क्योंकि यह बहुत पहली पंक्ति है b, और HeadCountऔर TailCountदोनों को कम होना चाहिए Count(जो ज्ञात है), यह स्वाभाविक रूप से सीमित करने की एक विधि के रूप में कार्य करता है कि पुनरावर्ती शब्द कितनी बार मेल कर सकता है, और इस कारण कार्यक्रम हमेशा समाप्त हो सकता है।

अगला कदम यह है कि इसे थोड़ा नीचे कर दिया जाए। सफेद स्थान को निकाल, एकल चरित्र चर नाम का उपयोग करते हुए, जैसे संक्षिप्त रूपों का उपयोग कर :-के लिए ifऔर ,के लिए and, का उपयोग कर setofके बजाय listof(यह एक छोटा नाम है और इस मामले में एक ही परिणाम का उत्पादन), और का उपयोग कर sort0(X,X)के बजाय is_sorted(X)(क्योंकि is_sortedवास्तव में कोई वास्तविक कार्य नहीं है, मैंने इसे बनाया):

b([],0).
b([H|T],N):-N#=A+B+1,b(H,A),b(T,B),sort0([H|T],[H|T]).
c(X,Y):-setof(A,b(A,X),L),length(L,Y).

यह काफी कम है, लेकिन बेहतर करना संभव है। महत्वपूर्ण जानकारी यह है कि [H|T]सूची सिंटैक्स के रूप में वास्तव में क्रिया है। जैसा कि लिस्प प्रोग्रामर्स को पता होगा, एक सूची मूल रूप से सिर्फ कॉन्स कोशिकाओं से बनी है, जो मूल रूप से सिर्फ ट्यूपल हैं, और शायद ही इस कार्यक्रम का कोई भी हिस्सा लिस्ट बिलिन का उपयोग कर रहा है। प्रोलॉग के पास बहुत कम टुपल सिंटैक्स हैं (मेरा पसंदीदा है A-B, लेकिन मेरा दूसरा पसंदीदा है A/B, जो मैं यहां उपयोग कर रहा हूं क्योंकि यह इस मामले में आसानी से पढ़ा जाने वाला डिबग आउटपुट पैदा करता है); और हम nilसूची के अंत के लिए अपना एकल-चरित्र भी चुन सकते हैं , बजाय दो-चरित्र के साथ अटक जाने के [](मैंने चुना x, लेकिन मूल रूप से कुछ भी काम करता है)। इसलिए इसके बजाय [H|T], हम इसका उपयोग कर सकते हैं T/H, और आउटपुट प्राप्त कर सकते हैंb यह इस तरह दिखता है (ध्यान दें कि ट्यूल पर क्रमबद्ध क्रम सूची से थोड़ा अलग है, इसलिए ये ऊपर दिए गए क्रम में नहीं हैं):

x/x/x/x/x
x/x/x/(x/x)
x/(x/x)/(x/x)
x/x/(x/x/x)
x/(x/x/x/x)
x/x/(x/(x/x))
x/(x/x/(x/x))
x/(x/(x/x/x))
x/(x/(x/(x/x)))

यह उपर्युक्त नेस्टेड सूचियों की तुलना में पढ़ना कठिन है, लेकिन यह संभव है; मानसिक रूप से एस को छोड़ दें x, और /()एक बुलबुले के रूप में व्याख्या करें (या /बिना किसी सामग्री के साथ एक पतले बुलबुले के रूप में सादे , अगर इसके ()बाद कोई नहीं है), और तत्वों में 1 से लेकर 1 (यदि अव्यवस्थित) के ऊपर दिखाए गए सूची संस्करण के साथ पत्राचार है ।

बेशक, यह सूची प्रतिनिधित्व, बहुत कम होने के बावजूद, एक बड़ी खामी है; यह भाषा में नहीं बनाया गया है, इसलिए हम यह sort0जांचने के लिए उपयोग नहीं कर सकते हैं कि हमारी सूची को क्रमबद्ध किया गया है या नहीं। sort0वैसे भी काफी वाचालता है, हालांकि, इसे हाथ से करना बहुत बड़ा नुकसान नहीं है (वास्तव में, [H|T]सूची प्रतिनिधित्व पर हाथ से ऐसा करना बिल्कुल उसी बाइट्स के लिए आता है)। यहां महत्वपूर्ण अंतर्दृष्टि यह है कि सूची को क्रमबद्ध करने के लिए लिखित चेकों के रूप में कार्यक्रम, यदि इसकी पूंछ को क्रमबद्ध किया गया है, यदि इसकी पूंछ को क्रमबद्ध किया गया है, और इसी तरह; बहुत सारे निरर्थक चेक हैं, और हम इसका फायदा उठा सकते हैं। इसके बजाय, हम केवल यह सुनिश्चित करने के लिए जाँच करेंगे कि पहले दो तत्व क्रम में हैं (जो यह सुनिश्चित करता है कि सूची समाप्त हो जाएगी एक बार सूची और उसके सभी प्रत्ययों की जाँच हो जाएगी)।

पहला तत्व आसानी से सुलभ है; यह सिर्फ सूची का प्रमुख है H। दूसरा तत्व पहुंच के लिए कठिन है, हालांकि, और मौजूद नहीं हो सकता है। सौभाग्य से, xउन सभी ट्यूपलों से कम है जिन्हें हम विचार कर रहे हैं (प्रोलॉग के सामान्यीकृत तुलना ऑपरेटर के माध्यम से @>=), इसलिए हम एक सिंगलटन सूची के "दूसरे तत्व" पर विचार कर सकते हैं xऔर प्रोग्राम ठीक काम करेगा। जैसा कि वास्तव में दूसरे तत्व तक पहुंचने के लिए, सबसे कठिन तरीका तीसरा तर्क (एक आउट तर्क) जोड़ना है b, जो xआधार मामले Hमें और पुनरावर्ती मामले में वापस आता है; इसका मतलब है कि हम दूसरी पुनरावर्ती कॉल से आउटपुट के रूप में पूंछ के सिर को पकड़ सकते हैं B, और निश्चित रूप से पूंछ का सिर सूची का दूसरा तत्व है। अब bऐसा दिखता है:

b(x,0,x).
b(T/H,N,H):-N#=A+B+1,b(H,A,_),b(T,B,J),H@>=J.

आधार मामला काफी सरल है (खाली सूची, 0 की गिनती लौटाएं, खाली सूची का "पहला तत्व" है x)। पुनरावर्ती मामला पहले की तरह ही शुरू हो जाता है (केवल T/Hनोटेशन के साथ [H|T], और Hअतिरिक्त तर्क के रूप में); हम सिर पर पुनरावर्ती कॉल से अतिरिक्त तर्क की उपेक्षा करते हैं, लेकिन इसे Jपूंछ पर पुनरावर्ती कॉल में संग्रहीत करते हैं। फिर हमें केवल यह सुनिश्चित करना है कि सूची से कम Hया अधिक J(यानी "यदि सूची में कम से कम दो तत्व हैं, तो यह सुनिश्चित करने के लिए कि सूची समाप्त हो गई है)

दुर्भाग्य से, setofअगर हम cइस नई परिभाषा के साथ एक साथ पिछली परिभाषा का उपयोग करने का प्रयास करते हैं, तो एक फिट फेंकता है b, क्योंकि यह अप्रयुक्त मापदंडों को SQL के समान कम या ज्यादा तरीके से व्यवहार करता है GROUP BY, जो पूरी तरह से वह नहीं है जो हम चाहते हैं। हम जो चाहते हैं, उसे करने के लिए इसे फिर से कॉन्फ़िगर करना संभव है, लेकिन उस पुन: निर्माण में पात्रों की लागत होती है। इसके बजाय, हम उपयोग करते हैं findall, जिसमें एक अधिक सुविधाजनक डिफ़ॉल्ट व्यवहार होता है और यह केवल दो अक्षर लंबा है, जिससे हमें यह परिभाषा मिलती है c:

c(X,Y):-findall(A,b(A,X,_),L),length(L,Y).

और वह पूरा कार्यक्रम है; tersely बुलबुला पैटर्न उत्पन्न करते हैं, फिर उन्हें गिनते हुए बाइट्स का एक पूरा भार खर्च करते हैं ( findallजनरेटर को किसी सूची में बदलने के लिए हमें लंबे समय की आवश्यकता होती है , फिर दुर्भाग्य lengthसे उस सूची की लंबाई की जांच करने के लिए नाम दिया गया है, और एक फ़ंक्शन के लिए बॉयलरप्लेट)।


"प्रोलॉग के पास वास्तव में एक नक्शा नहीं है" भविष्यवाणी : प्रोलॉग में maplist/2-8विधेय होता है , हालांकि मुझे यकीन नहीं है कि यह यहां चीजों को कम कर देगा।
घातक

@Fatalize: हुह, ऐसा लगता है कि एक नए संस्करण में जोड़ा गया था। यह मेरे पास स्थापित करने के लिए दस्तावेज में नहीं है, और यह अभ्यास में काम नहीं करता है:| ?- maplist(reverse,[A,B]). uncaught exception: error(existence_error(procedure,maplist/2),top_level/0)

यह वास्तव में अजीब है; maplistएक बहुत ही आमतौर पर इस्तेमाल किया जाने वाला विधेय है जो प्रमुख प्रोलॉग डिस्ट्रीब्यूशन (जैसे SWI- प्रोलॉग और सिस्कस) में प्रदान किया जाता है
घातक

10

गणितज्ञ, 68 बाइट्स

मैं शर्त लगाता हूं कि (खरोंच से भी) मैथेमैटिका में इसे एक खरोंच से लागू किया जा सकता है, लेकिन यहां बिल्ट संस्करण है:

<<NumericalDifferentialEquationAnalysis`
Last@ButcherTreeCount[#+1]&

ButcherTreeCountइसलिए 0-अनुक्रमित है [#+1], और इसके तर्क तक सभी मानों की एक सूची देता है, इसलिए Last@। लेकिन अन्यथा यह इस समारोह के लिए बिल्टइन है। हालांकि, इसके लिए एक पैकेज लोड करने की आवश्यकता होती है, जो कि पहली पंक्ति करती है।


8
"बेशक मैथेमेटिका के लिए एक बिलिन है।"
orlp
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.