2014-11-21 11 views
5

का उपयोग करके क्रम में एक सूची को तीन में विभाजित करना मैं एक ऐसा फ़ंक्शन बनाने की कोशिश कर रहा हूं जो परिवर्तनीय लंबाई की सूची को क्रमशः लंबाई की तीन सूचियों में विभाजित करता है। निम्नलिखित इसे तीन में विभाजित करता है, लेकिन प्रक्रियाएं उन्हें एक ही समय में प्रत्येक सूची में डालती हैं।प्रोलॉग

जो मैं चाहता का एक उदाहरण है:

[1, 2, 3, 4, 5] -> [1, 2], [3, 4], [5] 

एक और उदाहरण होगा:

div([], [], [], []). 
div([X], [X], [], []). 
div([X,Y], [X], [Y], []). 
div([X,Y,Z|End], [X|XEnd], [Y|YEnd], [Z|ZEnd]):- 
    div(End, XEnd, YEnd, ZEnd). 
:

[8, 7, 6, 5, 4, 3, 2, 1] -> [8, 7, 6], [5, 4, 3], [2, 1]. 

निम्नलिखित कोड एक समय में प्रत्येक सूची में डालने से उन्हें विभाजन

यह कोड आउटपुट:

[1, 2, 3, 4, 5] -> [1, 4], [2, 5], [3] 

मैं इस समस्या को कैसे ठीक कर सकता हूं?

उत्तर

5

@ बोरीस द्वारा उत्तर समाप्त नहीं होता है जब पहली तर्क की सूची की लंबाई ज्ञात नहीं होती है। इस देखने के लिए, कोई एक साथ पहला लक्ष्य की तुलना में किसी भी आगे देखने के लिए की जरूरत है:

 
div(L, L1, L2, L3) :- 
    length(L, Len), false, 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

दूसरी ओर, अपने मूल कार्यक्रम quite nice termination properties था।

div(A,B,C,D) terminates_if b(A);b(B);b(C);b(D). 

दूसरे शब्दों में, समाप्ति सुनिश्चित करने के लिए, आप केवल एक ही तर्क की जरूरत है (या तो A या B या C या D) एक ठोस सूची है कि परिमित और जमीन (है होना करने के लिए: CTI निम्नलिखित इष्टतम समाप्ति संपत्ति दे दी है b(..) का मतलब है)। यह एक बहुत ही मजबूत समाप्ति की स्थिति है। यह वास्तव में एक दयालुता है कि तर्क फिट नहीं है! अपने कार्यक्रम को सामान्य क्यों नहीं करें? एकमात्र समस्या यह है कि यह सूची तत्वों को प्रतिबंधित करता है। इसलिए मैं _ द्वारा सूची सभी तत्वों के चर नाम बदल देगा:

gdiv([], [], [], []). 
gdiv([_], [_], [], []). 
gdiv([_,_], [_], [_], []). 
gdiv([_,_,_|End], [_|XEnd], [_|YEnd], [_|ZEnd]):- 
    gdiv(End, XEnd, YEnd, ZEnd). 

very same समाप्ति गुण इस कार्यक्रम के लिए पकड़।

हां, अब यह थोड़ा सामान्य है।बोरिस के समाधान अब पुनः प्रयोजन जा सकता है:

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    append(As, BsCs, Zs), 
    append(Bs, Cs, BsCs). 

मेरे पसंदीदा एक ही व्यक्त करने के लिए जिस तरह से नहीं बल्कि होगा:

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    phrase((seq(As), seq(Bs), seq(Cs)), Zs). 

seq//1 की परिभाषा के लिए other answers देखें।

+0

धन्यवाद @false। मैं यह भी समझता हूं कि आप मुझे इस प्रश्न के बाहर दिखाने की कोशिश कर रहे थे। – Mocking

2
div(L, L1, L2, L3) :- 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

क्या आप देखते हैं कि यह तीन सूचियों को कैसे विभाजित करता है? अब आप यह नहीं कहें कि आप L1, L2, और L3 सूचियों की अपेक्षा कब तक करते हैं। L की लंबाई प्राप्त करने के लिए आप length/2 का उपयोग कर सकते हैं और तीन परिणामों की लंबाई निर्धारित कर सकते हैं यदि आप नहीं चाहते हैं कि भविष्य में यह सामान्य हो।

चूंकि आप "अपेक्षाकृत लंबाई भी" कहते हैं, जो रिश्तेदार है और मुझे इसे किसी भी तरह की व्याख्या करने की आवश्यकता है, मान लीजिए कि आप एक सकारात्मक पूर्णांक लेन और एन, लेन = 3 एन के लिए, आपको len1 = len2 = len3 = n, के = 3 एन + 1 के लिए आपको len1 = n + 1, len2 = len3 = n मिलता है, और के = 3 एन + 2 के लिए आपको len1 = len2 = n + 1, len3 = n मिलता है। मैं आपको लंबाई की गणना करने का तरीका बताता हूं।

div(L, L1, L2, L3) :- 
    length(L, Len), 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 
+0

मैं 100% निश्चित नहीं हूं लेकिन मुझे लगता है कि आपने मेरी समस्या को गलत समझा। मैं पहली सूची को 3 सूचियों में विभाजित करने की कोशिश कर रहा हूं। – Mocking

+0

@ मॉकिंग क्या आप वास्तव में यह अनुमान लगाते हैं कि यह भविष्य क्या करता है? इसके अलावा, अभी भी स्पष्ट नहीं है कि परिणामी सूचियों की लंबाई पर कोई बाधा है। –

+0

क्षमा करें, मैंने अपनी समस्या को और स्पष्ट करने की कोशिश की। मैं परिवर्तनीय लंबाई की एक सूची को 3 (या अपेक्षाकृत भी) सूचियों में विभाजित करने की कोशिश कर रहा हूं। क्या यह वास्तव में उस मामले में मदद करेगा? – Mocking