मान्य ब्रेनफ़ ** k कार्यक्रमों में प्रवेश करें


41

Golunar / एकल सभी वैध एन्कोड करने के लिए एक रास्ता है Brainfuck कार्यक्रमों, लेकिन यह, एक गणन नहीं है, क्योंकि सबसे प्राकृतिक संख्या एक वैध कार्यक्रम के अनुरूप नहीं है।

इस चुनौती के उद्देश्य के लिए, एक डबल अनंत टेप मान लीजिए और कोई टिप्पणी नहीं, यानी, एक ब्रेनफैक कार्यक्रम वैध है अगर और केवल अगर इसमें केवल वर्ण <>+-.,[]और सभी बाएं और दाएं कोष्ठक शामिल हैं।

उदाहरण के लिए, खाली कार्यक्रम, ,[+][-]., [>+<[--].]और +[+[+][+[+]+]+]+.वैध Brainfuck कार्यक्रम, जबकि कर रहे हैं ][, और a[]नहीं कर रहे हैं।

कार्य

एक प्रोग्राम या फ़ंक्शन लिखें जो एक मान्य ब्रेनफक प्रोग्राम को इनपुट के रूप में स्वीकार करता है और एक प्राकृतिक संख्या ( 1 , 2 , 3 ,…) देता है, निम्नलिखित बाधाओं के साथ:

  • उत्पन्न आउटपुट सभी मान्य ब्रेनफक कार्यक्रमों के लिए अलग होना चाहिए।

  • प्रत्येक प्राकृतिक संख्या n के लिए , एक मान्य ब्रेनफक प्रोग्राम होना चाहिए जो इनपुट के रूप में प्रदान किए जाने पर आउटपुट n उत्पन्न करता है ।

अतिरिक्त नियम

  • 100 या उससे कम बाइट्स के ब्रेनफक कार्यक्रम को देखते हुए, आपका कार्यक्रम या फ़ंक्शन एक मिनट के भीतर समाप्त होना चाहिए।

    इसका मतलब है कि जब तक आप इनपुट से मेल नहीं खाते तब तक आप सभी मान्य ब्रेनफक कार्यक्रमों पर पुनरावृति नहीं कर सकते।

  • मानक नियम लागू होते हैं।


3
मैं इसे केवल अष्टक के रूप में एन्कोड करने के बारे में सोच रहा था लेकिन मिलान करने वाले कोष्ठक इस मुश्किल बना रहे हैं।
डंकेमेज़

क्या खाली कार्यक्रम एक मान्य ब्रेनफक प्रोग्राम है? यह एक प्राकृतिक पूर्णांक के लिए भी मैप किया जाना चाहिए?
orlp

9
करीबी वोट क्यों? यह एक आकर्षक सवाल है और समस्या एक महान गोल्फ के लिए आकार और विविधता के लिए होती है।
ट्राइकोप्लाक्स

1
@orlp हाँ, खाली कार्यक्रम उपरोक्त परिभाषा को संतुष्ट करता है
डेनिस

3
ब्रेनफुक में लिखे गए उत्तर को देखने के लिए अभी भी इंतजार कर रहा है ...
माइकल हैम्पटन

जवाबों:


16

पायथन 3, 443 158 155 154 134 131 128 124 117 116 115 बाइट्स

c=d=C=D=0
for e in input():v='[<>,.-+]'.find(e);d=d*8+v;c+=c<0<6<v;c-=d>1>v;C,D=(c,C+1,d,D)[v>6::2]
print(-~D*8**C)

कई बाइट्स Sp3000 और मिच श्वार्ट्ज के लिए धन्यवाद: डी

यह कैसे काम करता है:

यह सभी वैध बीएफ कार्यक्रमों को सभी संभव, वैध या अमान्य बीएफ कार्यक्रमों में मैप करता है, जो कि [एक-से-एक अनुपात में शुरू नहीं होते हैं । उसके बाद, नया प्रोग्राम केवल ऑक्टल में परिवर्तित हो जाता है।

यहाँ मानचित्रण सूत्र है:

  1. BF प्रोग्राम को 3 भागों में अलग करें। पहला भाग सबसे बड़ा उपसर्ग है जिसमें केवल [वर्ण होते हैं। तीसरा भाग सबसे बड़ा पोस्टफिक्स है जिसमें केवल ]वर्ण होते हैं। दूसरा भाग मध्य है।
  2. पहले भाग का निपटान। इन्हें बाद में फिर से जोड़ा जा सकता है।
  3. ]तीसरे भाग में सभी कोष्ठक निकालें [जो दूसरे भाग में कोष्ठक से मेल खाते हैं। इन्हें बाद में पुन: प्रतिष्ठित भी किया जा सकता है।
  4. दूसरे और तीसरे भाग को एक साथ मिलाएं।

यदि आप इस स्पष्टीकरण को नहीं समझते हैं, तो आप यहाँ शुरू होने वाले चैट में एक विस्तृत स्पष्टीकरण पा सकते हैं ।

संदर्भ के लिए, यहां पहले 20 कार्यक्रम हैं:

1 : 
2 : <
3 : >
4 : ,
5 : .
6 : -
7 : +
8 : []
9 : <[]
10 : <<
11 : <>
12 : <,
13 : <.
14 : <-
15 : <+
16 : [<]
17 : >[]
18 : ><
19 : >>
20 : >,

यहां पहले 1000 कार्यक्रम हैं: http://pastebin.com/qykBWhmD
यहां वह कार्यक्रम है जो मैंने उन्हें उत्पन्न करने के लिए उपयोग किया है: http://ideone.com/e8oTVl

यहाँ है Hello, World!:

>>> ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
457711481836430915510337664562435564418569135809989841510260388418118348571803953323858180392373

लघु वक्रोक्ति: आप किसी प्रोग्राम को 0 पर मैप नहीं कर सकते हैं ।
डेनिस

@ डेनिस क्या एक खाली प्रोग्राम को प्रोग्राम के रूप में गिना जाता है?
बीटा डिके


@ डेनिस मैं ठीक कर दूंगा कि जब मैं इसे गोल्फ दूंगा।
TheNumberOne

3
यह सरल है
गर्वित हेकलर

13

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

def f(s,o=0,d=0,D={}):T=s,o,d;x=D[T]=D[T]if T in D else~o and 0**o+sum(f(s[1:],cmp(c,"[")%-3-~o,d or cmp(c,s[0]))for c in"+,-.<>[]")if s else~d<0==o;return+x

अभी भी बहुत गोल्फ दिखता है, लेकिन मैं इसे अभी के लिए पोस्ट कर रहा हूं। यह थोड़ा कैशिंग के साथ पुनरावृत्ति का उपयोग करता है। आमतौर पर, D.getकैचिंग के लिए शॉर्ट सर्किट नहीं होता है, इसलिए मैं इस तरह से 9 बाइट्स नहीं बचा सकता ...

मानचित्रण पहले प्राथमिकता तय करता है, फिर ऑर्डर करने पर लेक्सोग्राफिक ऑर्डर "][><.-,+"(नीचे आउटपुट उदाहरण देखें)। मुख्य विचार उपसर्गों की तुलना करना है।

चर वर्तमान उपसर्ग के लिए अभी भी खुले हुए कोष्ठकों oकी संख्या पर नज़र रखता है [, जबकि चर dसंकेत देने वाले तीन मानों में से एक लेता है:

  • d = 1: वर्तमान उपसर्ग lexicographically पहले की तुलना में है s। इस उपसर्ग और लंबाई के साथ सभी कार्यक्रम जोड़ें <= s,
  • d = -1: वर्तमान उपसर्ग lexicographically बाद की तुलना में है s। इस उपसर्ग और लंबाई के साथ सभी कार्यक्रम जोड़ें < s
  • d = 0: वर्तमान उपसर्ग एक उपसर्ग है s, इसलिए हम dबाद में 1 या -1 में बदल सकते हैं ।

उदाहरण के लिए, यदि हमारे पास s = "[-]"और हमारा वर्तमान उपसर्ग है p = "+", क्योंकि pबाद में sलेक्सिकोग्राफिक की तुलना में हम केवल उन कार्यक्रमों को जोड़ना जानते pहैं जिनके साथ कड़ाई से तुलना की जाती है s

अधिक विस्तृत उदाहरण देने के लिए, मान लें कि हमारे पास एक इनपुट प्रोग्राम है s = "-[]"। पहला पुनरावर्ती विस्तार यह करता है:

  (o == 0)               # Adds a program shorter than s if it's valid
                         # For the first expansion, this is 1 for the empty program
+ f(s[1:], o=-1, d=1)    # ']', o goes down by one due to closing bracket
+ f(s[1:], o=1, d=1)     # '[', o goes up by one due to opening bracket
+ f(s[1:], o=0, d=1)     # '>'
+ f(s[1:], o=0, d=1)     # '<'
+ f(s[1:], o=0, d=1)     # '.', d is set to 1 for this and the previous branches
                         # since they are lexicographically earlier than s's first char
+ f(s[1:], o=0, d=0)     # '-', d is still 0 since this is equal to s's first char
+ f(s[1:], o=0, d=-1)    # ',', d is set to -1 for this and the later branches
                         # since they are lexicographically later than s's first char
+ f(s[1:], o=0, d=-1)    # '+'

ध्यान दें कि हम वास्तव में पुनरावृत्ति में उपसर्गों का उपयोग कैसे नहीं करते हैं - हम सभी उनके बारे में परवाह करते हैं जो चर के माध्यम से कैप्चर किए जाते हैं d, oऔर सिकुड़ते इनपुट प्रोग्राम s। आप ऊपर बहुत अधिक पुनरावृत्ति देखेंगे - यह वह जगह है जहाँ कैशिंग आता है, जिससे हम समय सीमा के भीतर 100-चर कार्यक्रमों को अच्छी तरह से संसाधित कर सकते हैं।

जब sखाली होता है, तो हम देखते हैं (d>=0 and o==0), जो यह तय करता है कि क्या 1 वापस करना है (इस कार्यक्रम को गिनें क्योंकि यह शाब्दिक रूप से प्रारंभिक / बराबर है और कार्यक्रम मान्य है), या 0 (इस कार्यक्रम की गिनती न करें)।

किसी भी संतृप्ति के साथ o < 0तुरंत रिटर्न 0, क्योंकि इस उपसर्ग के साथ किसी भी कार्यक्रम की ]तुलना में अधिक एस है [, और इस प्रकार अमान्य हैं।


पहले 20 आउटपुट हैं:

 1
> 2
< 3
. 4
- 5
, 6
+ 7
[] 8
>> 9
>< 10
>. 11
>- 12
>, 13
>+ 14
<> 15
<< 16
<. 17
<- 18
<, 19
<+ 20

@NumberOne के उत्तर के रूप में उसी हैलो वर्ल्ड उदाहरण का उपयोग करना:

>>> f("++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.")
3465145076881283052460228065290888888678172704871007535700516169748342312215139431629577335423L

4

पायथन 2, 505 (गोल्फ नहीं)

मुझे इस दृष्टिकोण को विकसित करने में मज़ा आया, लेकिन मैं इसे परेशान नहीं कर सकता क्योंकि यह अन्य दृष्टिकोणों की तुलना में प्रतिस्पर्धी नहीं है। मैं इसे विविधता के लिए और संभावित सौंदर्य रुचि के लिए पोस्ट कर रहा हूं। इसमें पुनरावृत्ति और गणित का एक सा शामिल है।

F={0:1}

def f(n):
    if n not in F:
        F[n]=6*f(n-1) + sum(f(i)*f(n-2-i) for i in range(n-1))

    return F[n]

def h(x):
    if x=='': return 0

    if len(x)==1: return '+-<>,.'.find(x)

    if x[0]!='[':
        return h(x[0]) * f(len(x)-1) + h(x[1:])

    d=i=1
    while d:
        if x[i]==']': d-=1
        elif x[i]=='[': d+=1
        i+=1

    a=i-2
    b=len(x)-i

    return 6*f(a+b+1) + sum(f(i)*f(a+b-i) for i in range(a)) + h(x[1:i-1]) * f(b) + h(x[i:])

def g(x):
    return sum(f(i) for i in range(len(x))) + h(x) + 1

print g(raw_input())

फ़ंक्शन f(n)लंबाई के मान्य ब्रेनफक कार्यक्रमों की संख्या को गिनाता है nh(x)लंबाई के नक्शे कार्यक्रमों nके लिए [0..f(n)-1], और g(x)प्रश्न में द्विभाजित रैंकिंग कार्य है।

मुख्य विचार यह है कि एक गैर-खाली कार्यक्रम या तो [6 गैर- []पात्रों में से किसी एक के साथ शुरू हो सकता है । पूर्व मामले में, हम मिलान के संभावित स्थानों ]पर संलग्न कर सकते हैं और संलग्न भाग पर और पूंछ पर (जहां पूंछ का अर्थ है प्रतिस्थापन के बाद ])। उत्तरार्द्ध मामले में, हम पूंछ पर पुनरावृत्ति कर सकते हैं (जहां पूंछ का मतलब पहले चरित्र को छोड़ दें)। इस तर्क का उपयोग गणना के लिए और कंप्यूटिंग रैंक के लिए दोनों के लिए किया जा सकता है।

छोटे कार्यक्रमों में हमेशा लंबे कार्यक्रमों की तुलना में कम रैंक होगा, और ब्रैकेट पैटर्न एक माध्यमिक निर्धारण कारक है। गैर []अक्षर "+ - <>, के अनुसार क्रमबद्ध हैं।" (जो मनमाना हो)।

उदाहरण के लिए n=4हमारे पास ये मामले हैं:

zxxx
[]xx
[x]x
[xx]

जहां zगैर- []चरित्र xके लिए खड़ा है और किसी भी चरित्र के लिए खड़ा है, प्रतिबंध के तहत ]जो प्रारंभिक से मेल खाना है [। उस क्रम के अनुसार कार्यक्रमों को रैंक किया जाता है, और xबाद के मामलों में दाहिने खंड पर बाएं अनुभाग को प्राथमिकता के साथ, उप- वर्गों पर पुनरावृत्ति होती है। रैंक गणना मिश्रित-मूलांक अंक प्रणाली के समान है, और fवर्तमान "मूलांक" की गणना के लिए महत्वपूर्ण है।


4

यह जवाब TheNumberOne , Enumerate वैध Brainf ** k कार्यक्रमों के उत्तर के लिए एक औपचारिक प्रमाण है , जहां यह ठीक अंक को समझने के लिए थोड़ा कठिन हो सकता है कि गणना क्यों सही है। यह समझना गैर-जरूरी है कि कुछ अमान्य प्रोग्राम क्यों नहीं हैं जो किसी वैध प्रोग्राम द्वारा कवर किए गए नंबर पर मैप करते हैं।

इस उत्तर के दौरान राजधानियों का उपयोग कार्यक्रमों को निरूपित करने के लिए किया जाता है, और लोअरकेस चर का उपयोग फ़ंक्शंस और पूर्णांक के लिए किया जाता है। ~ संघट्टन संचालक है।

प्रस्ताव 1:

फ़ंक्शन को उस उत्तर में वर्णित प्रोग्राम होने दें। तब हर प्रोग्राम U के लिए एक मान्य प्रोग्राम V मौजूद होता है जैसे कि f (U) = f (V)

परिभाषा 1:

बता दें कि g (X) [प्रोग्राम X में दिखाई देने वाली संख्या है , और h (X) ]दिखाई देने वाली संख्या है ।

परिभाषा 2:

इस कार्य को करने के लिए P (x) को परिभाषित करें:

P(x) = "" (the empty program) when x <= 0
P(x) = "]" when x = 1
P(x) = "]]" when x = 2
etcetera

परिभाषा 3:

एक प्रोग्राम X को देखते हुए, X1 को निरूपित करें, यह [वर्णों का सबसे बड़ा उपसर्ग है , X2 इसका केंद्र और X3 ]वर्णों का सबसे बड़ा प्रत्यय है ।

प्रस्ताव 1:

यदि g (U) = h (U) है तो U एक वैध प्रोग्राम है, और हम V = U ले सकते हैं। (तुच्छ मामला)।

यदि g (U) <h (U) है तो हम n = h (U) - g (U) [चिन्हों को प्रस्तुत करके V बना सकते हैं । स्पष्ट रूप से एफ (वी) = एफ (यू) के रूप [में उपसर्ग के सभी प्रतीकों को हटा दिया जाता है।

अब g (U)> h (U) पर विचार करें। टी = यू 2 ~ यू 3 को परिभाषित करें। यदि g (T) <= h (T) है, तो हम n = g (U) - h (U) [प्रतीकों को हटाकर V का निर्माण कर सकते हैं ।

तो हम मान सकते हैं कि h (T) <g (T)। निर्माण V = T ~ P (g (T) - h (T))।

हमें आगे बढ़ने के लिए तीन छोटे तथ्यों की आवश्यकता है:

दावा 1: g (U2) = g (T)

U3 में [इसकी परिभाषा के अनुसार कोई प्रतीक नहीं है । T = U2 ~ U3 के रूप में, इसके [प्रतीक पहले भाग में हैं।

दावा 2: h (U3) <g (T)

यह ध्यान देने योग्य है कि h (T) <g (T) और h (U3) <h (U3 ~ U2) = h (T) का उल्लेख है।

दावा 3: h (V3) = g (U2) - h (U2)

h(V3) = h(U3) + g(T) - h(T)                           using the construction of V
h(V3) = h(U3) + g(U2) + g(U3) - h(U2) - h(U3)         apply the definition of T
h(V3) = g(U2) - h(U2) *one term cancels, g(U3)        is always zero, as U3 contains only `]` symbols*

अब हम दिखाते हैं कि f (V) = f (U)।

f(U) = U2 ~ P(h(U3) - g(U2)) = U2                     claim 2, definition of P

f(V) = U2 ~ P(h(V3) - g(V2))
     = U2 ~ P(h(V3) - g(U2))
     = U2 ~ P(g(U2) - h(U2) - g(U2))                  claim 3
     = U2 ~ P(-h(U2))
     = U2                                             definition P

इससे प्रमाण पूरा हो जाता है। QED

चलो विशिष्टता भी करते हैं।

प्रस्ताव 2:

यू, वी दो अलग-अलग कार्यक्रम हैं, मान्य कार्यक्रम। फिर एफ (यू)! = एफ (वी)

यह पिछले प्रस्ताव की तुलना में काफी सीधा है।

मान लेते हैं कि U2 = V2। लेकिन तब U और V को अलग-अलग किया जा सकता है, क्रमशः n1 और U3 में n [और ]प्रतीकों को जोड़कर या हटाकर । फिर भी यह f के आउटपुट को बदल देता है, क्योंकि f ]प्रत्यय में बेजोड़ प्रतीकों की संख्या की गणना करेगा ।

इस प्रकार U2! = V2

जाहिर है, इससे विरोधाभास होता है। चूंकि U2 और V2 क्रमशः f (U) और f (V) के आउटपुट में समाहित हैं, वे अलग-अलग नहीं हो सकते हैं, सिवाय 'किनारे' के, जहां U2 U3 के साथ सम्‍मिलित है। लेकिन U2 और V2 के पहले और आखिरी प्रतीक परिभाषा के अनुसार [या नहीं हो सकते हैं ], जबकि वे केवल क्रमशः U1, U3, V1, V3 में अनुमत प्रतीक हैं और फिर से। इस प्रकार हमें U2 = V2 मिलता है। QED

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