बाइनरी पेड़ों की गणना करें


20

बाइनरी पेड़

एक बाइनरी ट्री तीन प्रकार के नोड्स वाला एक पेड़ है:

  • टर्मिनल नोड्स, जिनके कोई बच्चे नहीं हैं
  • एकतरफा नोड्स, जिनमें से प्रत्येक में एक बच्चा है
  • बाइनरी नोड्स, जिनके दो बच्चे हैं

हम बीएनएफ (बैकस-नौर फॉर्म) में दिए गए निम्नलिखित व्याकरण के साथ उनका प्रतिनिधित्व कर सकते हैं :

<e> ::= 
      <terminal>   
    | <unary>
    | <binary>

<terminal> ::= 
    "0"

<unary> ::= 
    "(1" <e> ")"

<binary> ::= 
    "(2" <e> " " <e> ")"

इस व्याकरण में नोड्स को प्रीऑर्डर में दिया गया है और प्रत्येक नोड को एक अंक द्वारा दर्शाया गया है जो कि इसके बच्चों की संख्या है।

मोटकिन संख्या

मोटज़किन संख्या ( OEIS ) ( विकिपीडिया ) की कई व्याख्याएँ हैं, लेकिन एक व्याख्या यह है कि nवें Motzkin संख्या nनोड्स के साथ अलग-अलग द्विआधारी पेड़ों की संख्या है । मोटज़किन संख्याओं की एक तालिका शुरू होती है

N          Motzkin number M(N)
1          1
2          1
3          2 
4          4 
5          9 
6         21 
7         51 
8        127 
    ...

उदाहरण M(5)9 है, और 5 नोड्स वाले नौ अलग-अलग बाइनरी पेड़ हैं

1      (1 (1 (1 (1 0))))  
2      (1 (1 (2 0 0)))  
3      (1 (2 0 (1 0)))  
4      (1 (2 (1 0) 0))  
5      (2 0 (1 (1 0)))  
6      (2 0 (2 0 0))  
7      (2 (1 0) (1 0))  
8      (2 (1 (1 0)) 0)  
9      (2 (2 0 0) 0)  

कार्य

नोड्स के nसाथ सभी अलग-अलग बाइनरी पेड़ों के इनपुट और आउटपुट के रूप में एक ही सकारात्मक पूर्णांक लें n

n1 से 5 के लिए उदाहरण कोष्ठक के साथ पठनीयता के लिए शामिल किया गया है

0

(1 0)

(1 (1 0))
(2 0 0)

(1 (1 (1 0)))
(1 (2 0 0))
(2 0 (1 0))
(2 (1 0) 0)

(1 (1 (1 (1 0))))
(1 (1 (2 0 0)))
(1 (2 0 (1 0)))
(1 (2 (1 0) 0))
(2 0 (1 (1 0)))
(2 0 (2 0 0))
(2 (1 0) (1 0))
(2 (1 (1 0)) 0)
(2 (2 0 0) 0)

इनपुट

इनपुट एक धनात्मक पूर्णांक होगा।

उत्पादन

आउटपुट को कई बाइनरी नोड्स के साथ अलग-अलग बाइनरी पेड़ों का एक समझदार प्रतिनिधित्व होना चाहिए। बीएनएफ व्याकरण द्वारा दिए गए सटीक स्ट्रिंग का उपयोग करना अनिवार्य नहीं है: यह पर्याप्त है कि इस्तेमाल किया गया वाक्यविन्यास पेड़ों का एक स्पष्ट प्रतिनिधित्व देता है। जैसे आप []इसके बजाय उपयोग कर सकते हैं , बाहरी ()कोष्ठक के [[]]बजाय कोष्ठक का एक अतिरिक्त स्तर []मौजूद है या गायब है, अतिरिक्त अल्पविराम या कोई अल्पविराम, अतिरिक्त स्थान, लघुकोष्ठक या कोई लघुकोष्ठक, आदि।

ये सभी समतुल्य हैं:

(1 (2 (1 0) 0))  
[1 [2 [1 0] 0]]  
1 2 1 0 0  
12100  
(1 [2 (1 0) 0])  
.:.--  
*%*55  
(- (+ (- 1) 1))
-+-11

इसके अलावा एक टिप्पणी में @xnor द्वारा निर्धारित विविधता। चूंकि इसे एक प्रारूप में अनुवाद करने का एक तरीका है जिसे समझा जा सकता है कि यह स्वीकार्य है।

[[[]][]]  is (2 (1 0) 0)

इसे समझने में आसानी करने के लिए कुछ को इस तरह []से बदलना()

[([])()]

अब अगर आप साथ शुरू करते हैं

[]

फिर एक बाइनरी डालें जिसमें आपको दो अभिव्यक्तियाँ मिलें

 [()()] which is 2

और फिर पहले के लिए () एक यूनरी डालें जिसमें आपको प्राप्त होने वाली एक अभिव्यक्ति की आवश्यकता हो

 [([])()] which is 21

लेकिन चूंकि []या ()कोई आंतरिक ब्रैकेटिंग 0 का प्रतिनिधित्व नहीं कर सकती है, जिसके लिए आपको और अधिक अभिव्यक्ति की आवश्यकता नहीं है जो आप इसकी व्याख्या कर सकते हैं

 2100

ध्यान दें कि उत्तर को अनंत स्मृति के साथ सैद्धांतिक रूप से काम करना चाहिए, लेकिन स्पष्ट रूप से कार्यान्वयन-निर्भर परिमित इनपुट के लिए स्मृति से बाहर चलेगा।

आउटपुट की भिन्नता

BNF             xnor       Christian   Ben
b(t, b(t, t))   [{}{{}{}}] (0(00))     (1, -1, 1, -1)                         
b(t, u(u(t)))   [{}{(())}] (0((0)))    (1, -1, 0, 0)           
b(u(t), u(t))   [{()}{()}] ((0)(0))    (1, 0, -1, 0)                     
b(b(t, t), t)   [{{}{}}{}] ((00)0)     (1, 1, -1, -1)              
b(u(u(t)), t)   [{(())}{}] (((0))0)    (1, 0, 0, -1)                          
u(b(t, u(t)))   [({}{()})] ((0(0)))    (0, 1, -1, 0)                          
u(b(u(t), t))   [({()}{})] (((0)0))    (0, 1, 0, -1)                        
u(u(b(t, t)))   [(({}{}))] (((00)))    (0, 0, 1, -1)                          
u(u(u(u(t))))   [(((())))] ((((0))))   (0, 0, 0, 0)  

डुप्लीकेट पेड़ों की जांच के लिए एक संभावित स्थान

डुप्लिकेट की जांच करने के लिए एक जगह M (5) के साथ है।
इस एक पेड़ को M (4) पेड़ों से M (5) के लिए दो बार उत्पन्न किया गया था

(2 (1 0) (1 0))  

के लिए एक यूनीरी शाखा जोड़कर पहला

(2 (1 0) 0)

और दूसरा एक अनार्य शाखा को जोड़कर

(2 0 (1 0))

बीएनएफ को समझना

BNF सरल नियमों से बना है:

<symbol> ::= expression

बाईं ओर जहां एक प्रतीक नाम है, जो चारों ओर से घिरा हुआ है <>
सही पर प्रतीक के निर्माण के लिए अभिव्यक्ति है। कुछ नियम निर्माण में अन्य नियमों का उपयोग करते हैं, जैसे

<e> ::= <terminal>

e a हो सकता है terminal

और कुछ नियमों में ऐसे अक्षर होते हैं जिनका उपयोग प्रतीक के निर्माण में किया जाता है, जैसे

<terminal> ::= "0"

terminal सिर्फ चरित्र शून्य है।

कुछ नियमों के निर्माण के कई तरीके हैं, उदाहरण के लिए

<e> ::= 
      <terminal>   
    | <unary>
    | <binary>

एक या एक या एक eहो सकता है ।<terminal><unary><binary>

और कुछ नियम भागों का एक क्रम है, उदाहरण के लिए

<unary> ::= "(1" <e> ")"

unaryअक्षर है (1जिसके बाद निर्माण eकिया जा सकता है उसके बाद के लिए )

आप हमेशा शुरुआती नियम से शुरू करते हैं, जो इसके लिए है <e>

कुछ सरल उदाहरण:

सबसे सरल क्रम बस है 0। इसलिए हम शुरुआती नियम से शुरू करते हैं <e>और देखते हैं कि तीन विकल्प हैं:

  <terminal>   
| <unary>
| <binary>

तो पहले वाला ले लो <terminal>। अब एक टर्मिनल के पास कोई विकल्प नहीं है और है 0। तो बदलने के <terminal>साथ 0में <e>शासन और आपका काम हो गया।

फिर अगला है (1 0)। के साथ शुरू करो <e>और उपयोग नियम <unary>है जो

"(1" <e> ")"

अब इसकी जरूरत है <e>ताकि हम वापस जाएं <e>और तीन में से एक का चुनाव करें, इस बार चुनने का, <terminal>जो देता है 0। जगह 0में (1 <e> )देता है (1 0), और यह बदल दिया जाता है में <unary>तो <e>है (1 0)


तो, एक बाइनरी ट्री? "एक द्विआधारी वृक्ष एक वृक्ष डेटा संरचना है जिसमें प्रत्येक नोड में अधिकतम दो बच्चे हैं"
fəˈnɛtɪk

3
आपका विवरण एक द्विआधारी वृक्ष है। बाइनरी पेड़ों को 2 बच्चे होने की आवश्यकता नहीं है। इसका सीधा मतलब है कि उनके अधिकतम 2 बच्चे हैं। मेरा मानना ​​है कि यूनीरी-बाइनरी सिर्फ एक अधिक विशिष्ट शब्द है जिसका वास्तव में कुछ अलग मतलब नहीं है।
fɛn

यह स्पष्ट करने पर विचार करें कि "बीएनएफ" हममें से उन लोगों के लिए क्या है जो कंप्यूटर वैज्ञानिक नहीं हैं
लुइस मेन्डो

1
@GuyCoder मेरी बात है, अगर कोई "बीएनएफ" देखता है और नहीं जानता है कि इसका क्या मतलब है कि उन्हें बंद कर दिया जाए और पढ़ना बंद कर दिया जाए। शायद संक्षिप्त नाम के बजाय नाम का उपयोग करना और विकिपीडिया के लिए एक लिंक जोड़ना पर्याप्त होगा
लुइस मेंडू

4
@ mbomb007 नाम बदल गया। मुझे उसके लिए एक पीयर-प्रेशर अवार्ड मिलना चाहिए। :)
गाय कोडर

जवाबों:


12

हास्केल, 68 बाइट्स

t 0=[""]
t 1=["0"]
t n=['(':x++y++")"|k<-[1..n-1],x<-t k,y<-t$n-k-1]

टर्मिनल नोड्स का प्रतिनिधित्व 0, यूनरी और बाइनरी नोड्स द्वारा किया जाता है (e)(ee), इसलिए दो तीन-नोड के पेड़ के रूप में दिए गए हैं (00)और ((0))

उदाहरण:

*Main> t 5
["(0(00))","(0((0)))","((0)(0))","((00)0)","(((0))0)","((0(0)))","(((0)0))","(((00)))","((((0))))"]
*Main> length $ t 8
127
*Main> length $ t 15
113634 

5

CJam (37 बाइट्स)

0aa{_2m*2\f+1Y$f+++:e__&}qi:A*{,A=},p

ऑनलाइन डेमो । ध्यान दें कि यह बहुत कुशल नहीं है, और आप संभवतः 5ऑनलाइन इनपुट की गणना करने का प्रयास नहीं करना चाहते हैं ।

पालन ​​करने के लिए विच्छेदन।


5

पायथ ( 24 21 19 बाइट्स)

यह मेरे पायथन 3 समाधान पर आधारित है ।

f!|sTf<sY0._T^}1_1t

यह मेरी पहली बार पाइथ का उपयोग कर रहा है इसलिए यह अभी भी गोल्फ होने की संभावना है।

उदाहरण , इनपुट होने पर आउटपुट 4:

[[1, 0, -1], [1, -1, 0], [0, 1, -1], [0, 0, 0]]

1 एक द्विआधारी नोड का प्रतिनिधित्व करता है, 0 एक असमान नोड का प्रतिनिधित्व करता है, और -1 एक टर्मिनल नोड का प्रतिनिधित्व करता है। हर पेड़ के अंत में एक निहित टर्मिनल नोड होता है।

स्पष्टीकरण :

f!|sTf<sY0._T^}1_1t
f                    filter
             ^    t  length n-1 lists of elements
              }1_1   from [1, 0, -1]
 !|                  for when both
   sT                sum of list is 0, and
     f    ._T        for each prefix of list,
      <sY0           sum of prefix is non-negative.


4

ब्रेनफक, 107 बाइट्स

,>++>-[-[<-[<-[>>[[>+<-]<]>+>[[<+>>>>>+<<<<-]>]>>++>,++++>]>[<+>-[+>>]>[<->[.<<<
<<]+[->+]+>>>]]]]<[[,<]<]<]

प्रारूपित:

,>++>-
[
  -
  [
    <-
    [
      <-
      [
        >>
        [[>+<-]<]
        >+>
        [[<+> >>>>+<<<<-]>]
        >>++>,++++>
      ]
      >
      [
        <+>-
        [
          +>>
        ]
        >
        [
          <->[.<<<<<]
          +[->+]
          +>>>
        ]
      ]
    ]
  ]
  <
  [
    [,<]
    <
  ]
  <
]

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

इनपुट को बाइट के रूप में लिया जाता है , और पेड़ 12100को इस रूप में दर्शाया जाता है \x01\x02\x03\x02: वापस कन्वर्ट करने, अनुवाद करने tr/\x01\x02\x03/012/, स्ट्रिंग को उलटने और एक अंतिम जोड़ने के लिए 0। पेड़ अलग हो जाते हैं \xfe। (उत्पादन जैसे पहले बदलकर पढ़ने में आसान बनाया जा सकता है -में -36और .में +47.-47, जहां -36साधन 36 के एक स्ट्रिंग -वर्ण, आदि)

यह दृष्टिकोण संपत्ति का उपयोग करता है (जो कि बेन फ्रैंकेल ने भी उपयोग किया है): -1, 0, 1अंतिम -1नोड के रूप में संभव नोड्स की उपेक्षा और पर विचार करना , एक सूची एक वैध पेड़ का प्रतिनिधित्व करती है अगर और केवल अगर (1) सूची के सभी उपसर्गों में गैर-नकारात्मक योग है, और (2) पूरी सूची का योग बराबर है 0। मध्यवर्ती नोड उत्पन्न करते समय पहली स्थिति बनाए रखी जाती है, इसलिए केवल दूसरी स्थिति को अंत में जांचने की आवश्यकता होती है।

टेप को 5-नोड कोशिकाओं में विभाजित किया गया है,

i d x 0 0

iसूचकांक कहां है (बाएं से दाएं की ओर), dआंशिक राशि है, और xतत्व है।

नियंत्रण प्रवाह का स्केच:

take n and push initial node
while stack is non-empty:
    if rightmost node can be decremented:
        decrement rightmost node
        if there are less than n nodes:
            push new node
        else if valid tree:
            print
    else:
        backtrack (pop)

ध्यान दें कि कभी-कभी एक मूल्य को संग्रहीत किया जाता है या वास्तविक (वैचारिक) मूल्य से एक या दो से अधिक के रूप में आरंभ किया जाता है और आवश्यकतानुसार समायोजित किया जाता है।


3

अजगर 3 ( 138 134 128 121 119 बाइट्स)

from itertools import*
lambda n:[any(sum(t[:k])<0for k in range(n))|sum(t)or print(t)for t in product(*[[-1,0,1]]*~-n)]

उदाहरण के लिए आउटपुट n=5:

(0, 0, 0, 0)
(0, 0, 1, -1)
(0, 1, -1, 0)
(0, 1, 0, -1)
(1, -1, 0, 0)
(1, -1, 1, -1)
(1, 0, -1, 0)
(1, 0, 0, -1)
(1, 1, -1, -1)

1 एक द्विआधारी नोड का प्रतिनिधित्व करता है, 0 एक असमान नोड का प्रतिनिधित्व करता है, और -1 एक टर्मिनल नोड का प्रतिनिधित्व करता है। हर पेड़ के अंत में एक निहित टर्मिनल नोड होता है।

कार्यक्रम के चारों ओर बहुत समय लग रहा है n=17


3

जावास्क्रिप्ट (फ़ायरफ़ॉक्स 30-57), 79 बाइट्स

f=(m,l=0)=>m?[for(n of[1,0,-1])if(l>n&l<=m+n)for(a of f(m-1,l-n))[...a,n]]:[[]]

जहां -1एक टर्मिनल, 0एक असमान नोड और 1एक बाइनरी नोड का प्रतिनिधित्व करता है । m=14मेरे पीसी पर धीमी गति से शुरू होता है । पुनरावर्ती वृक्ष के अंत से वापस काम करता है।

  • बेहिसाब नोड्स की संख्या lइस तथ्य से सीमित है कि अंत में केवल 1 नोड बचा रह सकता है।
  • अगले नोड nका प्रकार अपने बच्चों के होने के लिए पर्याप्त बेहिसाब नोड्स होने की आवश्यकता से सीमित है।

2

प्रोलोग, 149 144 138 137 131 107 बाइट्स

e(L,L)-->[0].

e([_|A],L)--> 
    [1],
    e(A,L).

e([_,_|A],L)--> 
    [2],
    e(A,B), 
    e(B,L).

e(M,E):-                   
    length([_|L],M),        
    e(L,[],E,[]).           

?- e(5,S).
S = [1, 1, 1, 1, 0] ;
S = [1, 1, 2, 0, 0] ;
S = [1, 2, 0, 1, 0] ;
S = [1, 2, 1, 0, 0] ;
S = [2, 0, 1, 1, 0] ;
S = [2, 0, 2, 0, 0] ;
S = [2, 1, 0, 1, 0] ;
S = [2, 1, 1, 0, 0] ;
S = [2, 2, 0, 0, 0].

और समाधान गिनने के लिए

e_count(N,Count) :-
    length([_|Ls], N),
    findall(., phrase(e(Ls,[]),E), Sols),
    length(Sols, Count).

?- e_count(N,Count).
N = Count, Count = 1 ;
N = 2, Count = 1 ;
N = 3, Count = 2 ;
N = Count, Count = 4 ;
N = 5, Count = 9 ;
N = 6, Count = 21 ;
N = 7, Count = 51 ;
N = 8, Count = 127 ;
N = 9, Count = 323 ;
N = 10, Count = 835 ;
N = 11, Count = 2188 ;
N = 12, Count = 5798 ;
N = 13, Count = 15511 ;
N = 14, Count = 41835 ;
N = 15, Count = 113634 

1

पायथन, 71 बाइट्स

f=lambda n:{(a+b,)for k in range(n)for a in f(k)for b in f(n+~k)}or[()]

यह पेड़ों को नेस्टेड टुपल्स के रूप में प्रतिनिधित्व करता है ((((),), ()),), जैसे कि ((())())कॉमा, रिक्त स्थान और सबसे बाहरी को हटाकर रूपांतरित किया जा सकता है ()

पहले वाला 76-बाइट संस्करण:

f=lambda n:{'('+a+b+')'for k in range(n)for a in f(k)for b in f(n+~k)}or['']

1

CJam, 38 बाइट्स

एक अलग दृष्टिकोण का उपयोग करता है जो पीटर टेलर का सीजेएम उत्तर देता है।

3rim*{:(1\+[{1$+}*])\:(_:z#|!},

आउटपुट कुछ इस तरह होगा 1110120020102100। प्रत्येक पेड़ nअंकों का एक समूह है (जहां nइनपुट संख्या है)।

मूल विचार है कि हम अंकों के प्रत्येक संभव स्ट्रिंग उत्पन्न है 0, 1और 2, और उसके बाद ही जो कि अच्छी तरह से गठित पेड़ हैं फ़िल्टर करें।

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