मैं सभी कार्यों के सेट पर एक शाखा और बाध्य खोज लिखने की कोशिश कर रहा हूँ f: D -> R, जहां डोमेन का आकार (- | D | ~ ~ 20) है और सीमा बहुत बड़ी है (| R | ~ 2 ^ 20 )। प्रारंभ में, मैं निम्नलिखित समाधान के साथ आया था।
(builder (domain range condlist partial-map)
(let ((passed? (check condlist partial-map)))
(cond
((not passed?) nil)
(domain (recur-on-first domain range condlist partial-map '()))
(t partial-map))))
(recur-on-first (domain range condlist partial-map ignored)
(cond
((null range) nil)
(t (let ((first-to-first
(builder (cdr domain)
(append ignored (cdr range))
condlist
(cons (cons (car domain) (car range)) partial-map))))
(or first-to-first
(recur-on-first domain
(cdr range)
condlist
partial-map
(cons (car range) ignored))))))))
यहां condlist
फ़ंक्शन builder
का पैरामीटर उन स्थितियों की एक सूची है जिन्हें किसी समाधान द्वारा संतुष्ट किया जाना चाहिए। check
शर्तों की सूची में किसी भी तत्व का उल्लंघन होने पर फ़ंक्शन शून्य हो जाता है partial-map
। फ़ंक्शन recur-on-first
डोमेन में पहले तत्व को सीमा में पहले तत्व को असाइन करता है और वहां से एक समाधान बनाने की कोशिश करता है। इस प्रक्रिया recur-on-first
को विफल करने के लिए खुद को हल करने का प्रयास करता है और एक समाधान का निर्माण करता है जो कि सीमा में पहले तत्व के अलावा किसी अन्य तत्व के लिए डोमेन में पहला तत्व प्रदान करता है। हालाँकि, इसे एक सूची को बनाए रखना होगा जो ignored
इन परित्यक्त तत्वों (जैसे श्रेणी में पहला तत्व) को संग्रहीत करता है क्योंकि वे डोमेन में कुछ अन्य तत्वों की छवियां हो सकती हैं।
दो समस्याएं हैं जो मैं इस समाधान के साथ देख सकता हूं। पहला यह है कि सूचियाँ ignored
और range
फ़ंक्शन recur-on-first
बहुत बड़े हैं और append
उन्हें एक महंगा ऑपरेशन है। दूसरी समस्या यह है कि समाधान की पुनरावृत्ति गहराई सीमा के आकार पर निर्भर करती है।
इसलिए मैं निम्नलिखित समाधान के साथ आया, जो रेंज में तत्वों को संग्रहीत करने के लिए दोगुनी लिंक की गई सूचियों का उपयोग करता है। कार्य start
, next
और end
दोगुनी लिंक की गई सूची पर पुनरावृति करने के लिए सुविधाएं प्रदान करते हैं।
(builder (domain range condlist &optional (partial-map nil))
(block builder
(let ((passed? (check condlist partial-map)))
(cond
((not passed?) nil)
(domain (let* ((cur (start range))
(prev (dbl-node-prev cur)))
(loop
(if (not (end cur))
(progn
(splice-out range cur)
(let ((sol (builder (cdr domain)
range
condlist
(cons (cons (car domain) (data cur)) partial-map))))
(splice-in range prev cur)
(if sol (return-from builder sol)))
(setq prev cur)
(setq cur (next cur)))
(return-from builder nil)))))
(t partial-map))))))
पहले समाधान के रनटाइम की तुलना में दूसरे समाधान का रनटाइम बहुत बेहतर है। append
पहले समाधान में आपरेशन में और एक दोगुना लिंक्ड सूची से बाहर स्प्लिसिंग तत्वों ने ले ली है (इन आपरेशनों लगातार समय कर रहे हैं) और प्रत्यावर्तन गहराई केवल डोमेन के आकार पर निर्भर करता है। लेकिन इस समाधान के साथ मेरी समस्या यह है कि यह C
स्टाइल कोड का उपयोग करता है। तो मेरा सवाल ये है।
क्या कोई ऐसा समाधान है जो दूसरे समाधान के रूप में कुशल है लेकिन setf
s और परस्पर डेटा संरचनाओं का उपयोग नहीं करता है ? दूसरे शब्दों में, क्या इस समस्या का एक कुशल कार्यात्मक प्रोग्रामिंग समाधान है?